diff options
| -rw-r--r-- | client/commands.h | 2 | ||||
| -rw-r--r-- | client/i18n/en_us.h | 3 | ||||
| -rw-r--r-- | client/main.c | 19 | ||||
| -rw-r--r-- | client/main.h | 1 | ||||
| -rw-r--r-- | client/serial.c | 11 | ||||
| -rw-r--r-- | client/setup.c | 7 | ||||
| -rw-r--r-- | client/ui.c | 6 | ||||
| -rw-r--r-- | client/ui_dirc.c | 2 | ||||
| -rw-r--r-- | protocol.md | 8 | ||||
| -rw-r--r-- | robot/hypervisor.h | 13 | ||||
| -rw-r--r-- | robot/makefile | 2 | ||||
| -rw-r--r-- | robot/sercomm.c | 43 | ||||
| -rw-r--r-- | robot/sim.h | 2 | ||||
| -rw-r--r-- | shared/consts.h | 5 | ||||
| -rw-r--r-- | shared/errcatch.h | 2 | 
15 files changed, 103 insertions, 23 deletions
diff --git a/client/commands.h b/client/commands.h index 5a12424..02ae313 100644 --- a/client/commands.h +++ b/client/commands.h @@ -4,6 +4,8 @@  #include "../shared/modes.h"  #include "serial.h" +void w2_send_bin(w2_s_bin *data); +  void w2_send_info();  void w2_send_ping();  void w2_send_mode(w2_e_mode mode); diff --git a/client/i18n/en_us.h b/client/i18n/en_us.h index 206e689..5547db5 100644 --- a/client/i18n/en_us.h +++ b/client/i18n/en_us.h @@ -1,5 +1,8 @@  #pragma once +#define W2_UI_CLI_USAGE "usage: %s <serial port>\n" +#define W2_UI_CLI_SERPORT_ERROR "serial port open fout\n" +#define W2_UI_CLI_INITSCR_FAIL "ncurses initscr() failed\n"  #define W2_UI_CONN_STAT_CONNECTED "connected"  #define W2_UI_CONN_STAT_DISCONNECTED "disconnected"  #define W2_UI_CONN_STAT_PING "ping" diff --git a/client/main.c b/client/main.c index 8fe6d8e..00f686a 100644 --- a/client/main.c +++ b/client/main.c @@ -1,10 +1,15 @@  #include "main.h"  #include "../shared/errcatch.h" +#include "../shared/consts.h"  #include "serial.h"  #include "setup.h"  #include "ui.h" +#include "time.h" +#include "commands.h" -w2_s_client_state g_w2_state; +w2_s_client_state g_w2_state = { +	.ping_received = true +};  int main(int argc, char **argv) {  	w2_client_setup(argc, argv); @@ -13,5 +18,17 @@ int main(int argc, char **argv) {  		w2_serial_main();  		w2_errcatch_main();  		w2_ui_main(); + +		if (!g_w2_state.ping_received && w2_timer_end(W2_TIMER_PING) > W2_PING_TIMEOUT) { +			g_w2_state.ping_timeout = true; +			g_w2_state.connected = false; +			w2_errcatch_throw(W2_E_WARN_PING_TIMEOUT); +		} +		 +		if ((g_w2_state.ping_received && w2_timer_end(W2_TIMER_PING) > W2_PING_FREQUENCY) || g_w2_state.ping_timeout) { +			g_w2_state.ping_timeout = false; +			g_w2_state.ping_received = false; +			w2_send_ping(); +		}  	}  } diff --git a/client/main.h b/client/main.h index e581b3c..cc4c728 100644 --- a/client/main.h +++ b/client/main.h @@ -6,6 +6,7 @@ typedef struct {  	unsigned int ping;  	uint8_t ping_id;  	bool ping_received; +	bool ping_timeout;  	bool connected;  	uint8_t battery_level; diff --git a/client/serial.c b/client/serial.c index e42bc0b..743fe76 100644 --- a/client/serial.c +++ b/client/serial.c @@ -5,19 +5,27 @@  #include "main.h"  #include "serial.h"  #include "time.h" +#include "commands.h"  void w2_serial_main() {  	int temp;  	while ((temp = w2_serial_read()) != -1) w2_serial_parse(temp);  } -void w2_cmd_ping_tx(w2_s_bin *data) { +void w2_cmd_ping_rx(w2_s_bin *data) {  	W2_CAST_BIN(w2_s_cmd_ping_tx, data, cast);  	if (g_w2_state.ping_received) return;  	if (g_w2_state.ping_id != cast->id) return; +  	g_w2_state.ping			 = w2_timer_end(W2_TIMER_PING);  	g_w2_state.ping_received = true; +	g_w2_state.ping_timeout = false; +	g_w2_state.connected = true; +} + +void w2_cmd_ping_tx(w2_s_bin *data) { +	w2_send_bin(data);  }  void w2_cmd_expt_tx(w2_s_bin *data) {} @@ -33,7 +41,6 @@ void w2_cmd_info_tx(w2_s_bin *data) {  	memcpy(&g_w2_state.info, data->data, sizeof(w2_s_cmd_info_tx));  } -void w2_cmd_ping_rx(w2_s_bin *data) { return; }  void w2_cmd_mode_rx(w2_s_bin *data) { return; }  void w2_cmd_sped_rx(w2_s_bin *data) { return; }  void w2_cmd_dirc_rx(w2_s_bin *data) { return; } diff --git a/client/setup.c b/client/setup.c index 50395e0..fd37c13 100644 --- a/client/setup.c +++ b/client/setup.c @@ -17,17 +17,17 @@ uint8_t g_w2_endianness;  void w2_client_setup(int argc, char **argv) {  	if (argc < 2) { -		printf("usage: %s <serial port>\n", argv[0]); +		printf(W2_UI_CLI_USAGE, argv[0]);  		exit(1);  	}  	if (w2_serial_open(argv[1]) == 0) { -		printf("serial port open fout\n"); +		printf(W2_UI_CLI_SERPORT_ERROR);  		exit(1);  	}  	if ((g_w2_ui_win = initscr()) == NULL) { -		printf("ncurses initscr() failed\n"); +		printf(W2_UI_CLI_INITSCR_FAIL);  		exit(1);  	}  	noecho(); @@ -38,7 +38,6 @@ void w2_client_setup(int argc, char **argv) {  	w2_cmd_setup_handlers();  	w2_send_info(); -	w2_send_ping();  	// check endianness  	g_w2_endianness = *_ptest; diff --git a/client/ui.c b/client/ui.c index e6e73f0..1cde52f 100644 --- a/client/ui.c +++ b/client/ui.c @@ -35,6 +35,12 @@ void w2_ui_paint() {  void w2_ui_paint_statusbar() {  	char temp[g_w2_ui_width]; + +	for (unsigned int i = 0; i < g_w2_ui_width; i++) temp[i] = ' '; +	mvaddnstr(0, 0, temp, g_w2_ui_width); +	mvaddnstr(1, 0, temp, g_w2_ui_width); +	mvaddnstr(2, 0, temp, g_w2_ui_width); +  	sprintf(temp, "%s, %ims %s",  			g_w2_state.connected ? W2_UI_CONN_STAT_CONNECTED : W2_UI_CONN_STAT_DISCONNECTED,  			g_w2_state.ping, W2_UI_CONN_STAT_PING); diff --git a/client/ui_dirc.c b/client/ui_dirc.c index 2965169..675913a 100644 --- a/client/ui_dirc.c +++ b/client/ui_dirc.c @@ -104,6 +104,6 @@ void w2_ui_dirc(bool first) {  	drive_l += drive_r * W2_DIRC_STP;  	drive_r += drive_l * W2_DIRC_STP; -	w2_send_dirc(drive_l, drive_r); +	// w2_send_dirc(drive_l, drive_r);  	w2_ui_dirc_paint(drive_l, drive_r);  } diff --git a/protocol.md b/protocol.md index 95ef835..9c45f56 100644 --- a/protocol.md +++ b/protocol.md @@ -66,9 +66,11 @@ in *both* the robot and client code `r <-- c` is referred to as `rx` and  `r  |`uint8_t`|opcode (`0x00 + 0` or `0x00 + 1`)|  |`uint8_t`|ping id| -**ping** sends back an identical message either way with the direction bit -toggled. _ping id_ is a random 8-bit value that makes sure the same ping -doesn't keep bouncing back and forth indefinitely. +**ping** sends back an identical message either way with the **same** direction +bit. _ping id_ is a random 8-bit value that identifies the ping message. this +is the only command that makes either the robot or client send a message with +an opcode not matching the respective sender. the direction bit indicates which +device initiated the ping message.  ### EXPT diff --git a/robot/hypervisor.h b/robot/hypervisor.h index 589d324..59398c6 100644 --- a/robot/hypervisor.h +++ b/robot/hypervisor.h @@ -4,9 +4,13 @@  #include <stdint.h> +#include "../shared/bool.h" +  /** amount of parallel timers */  #define W2_HYPERVISOR_TIMER_COUNT (1) +#define W2_TIMER_PING (0) +  extern uint64_t g_w2_hypervisor_cycles;  extern uint64_t g_w2_hypervisor_uptime_ms; @@ -15,10 +19,16 @@ extern unsigned long g_w2_hypervisor_ema_errcatch_ms;  extern unsigned long g_w2_hypervisor_ema_io_ms;  extern unsigned long g_w2_hypervisor_ema_mode_ms; +extern unsigned int g_w2_ping_ms; +extern uint8_t g_w2_ping_id; +extern bool g_w2_ping_received; +extern bool g_w2_ping_timeout; +extern bool g_w2_connected; +  /**   * backbone of all other modules   * - * stores global variables and controls when other modules run + * stores global state and controls when other modules run   */  void w2_hypervisor_main(); @@ -26,3 +36,4 @@ void w2_hypervisor_main();  void w2_hypervisor_time_start(uint8_t label);  /** stop timer with label `label` */  uint64_t w2_hypervisor_time_end(uint8_t label); + diff --git a/robot/makefile b/robot/makefile index 11e8509..ed700ae 100644 --- a/robot/makefile +++ b/robot/makefile @@ -6,7 +6,7 @@ MCU ?= atmega168  AVRDUDE_DEVICE ?= m168  PORT ?= /dev/ttyACM0 -SIM = true +# SIM = true  CFLAGS=-g -Wall $(DEVICE_SPECIFIC_CFLAGS) -Os  LDFLAGS=-Wl,-gc-sections -Wl,-relax diff --git a/robot/sercomm.c b/robot/sercomm.c index 519568d..afde48a 100644 --- a/robot/sercomm.c +++ b/robot/sercomm.c @@ -20,6 +20,12 @@ char g_w2_serial_buffer[W2_SERIAL_READ_BUFFER_SIZE] = {0};  uint8_t g_w2_serial_buffer_index					= 0;  uint8_t g_w2_serial_buffer_head						= 0; +unsigned int g_w2_ping_ms = 0; +uint8_t g_w2_ping_id = 0; +bool g_w2_ping_received = true; +bool g_w2_ping_timeout = false; +bool g_w2_connected = false; +  void w2_sercomm_main() {  #ifdef W2_SIM  	simprintfunc("w2_sercomm_main", ""); @@ -31,6 +37,27 @@ void w2_sercomm_main() {  		g_w2_serial_buffer_index = (g_w2_serial_buffer_index + 1) % W2_SERIAL_READ_BUFFER_SIZE;  	} +	// check time-out +	if (!g_w2_ping_received && w2_hypervisor_time_end(W2_TIMER_PING) > W2_PING_TIMEOUT) { +		g_w2_ping_timeout = true; +		w2_errcatch_throw(W2_E_WARN_PING_TIMEOUT); +	} +	// send ping every W2_TIMER_PING ms +	if ((g_w2_ping_received && w2_hypervisor_time_end(W2_TIMER_PING) > 1000) || g_w2_ping_timeout) { +		g_w2_ping_timeout = false; +		g_w2_ping_received = false; +		g_w2_ping_id = (uint8_t) rand(); + +		W2_CREATE_MSG_BIN(w2_s_cmd_ping_tx, msg, bin); +		msg->opcode = W2_CMD_PING | W2_CMDDIR_TX; +		msg->id		= g_w2_ping_id; + +		w2_sercomm_append_msg(bin); +		free(bin); + +		w2_hypervisor_time_start(W2_TIMER_PING); +	} +  	// send data  	while (g_w2_sercomm_offset != g_w2_sercomm_index) {  		w2_s_bin *data = g_w2_sercomm_buffer[g_w2_sercomm_offset]; @@ -62,15 +89,14 @@ void w2_sercomm_append_msg(w2_s_bin *data) {  #pragma GCC diagnostic push  #pragma GCC diagnostic ignored "-Warray-bounds" -void w2_cmd_ping_rx(w2_s_bin *data) { -	W2_CAST_BIN(w2_s_cmd_ping_rx, data, req); - -	W2_CREATE_MSG_BIN(w2_s_cmd_ping_tx, res_msg, res_bin); -	res_msg->opcode = W2_CMD_PING | W2_CMDDIR_TX; -	res_msg->id		= req->id; +void w2_cmd_ping_tx(w2_s_bin *data) { +	g_w2_ping_ms = w2_hypervisor_time_end(W2_TIMER_PING); +	g_w2_ping_received = true; +	g_w2_ping_timeout = false; +} -	w2_sercomm_append_msg(res_bin); -	free(res_bin); +void w2_cmd_ping_rx(w2_s_bin *data) { +	w2_sercomm_append_msg(data);  }  void w2_cmd_mode_rx(w2_s_bin *data) { @@ -150,7 +176,6 @@ void w2_cmd_cled_rx(w2_s_bin *data) { return; }  #pragma GCC diagnostic pop -void w2_cmd_ping_tx(w2_s_bin *data) {}  void w2_cmd_expt_tx(w2_s_bin *data) {}  void w2_cmd_mode_tx(w2_s_bin *data) {}  void w2_cmd_cord_tx(w2_s_bin *data) {} diff --git a/robot/sim.h b/robot/sim.h index 9d73585..14f0f74 100644 --- a/robot/sim.h +++ b/robot/sim.h @@ -16,7 +16,7 @@  #define DBG_ENABLE_CYCLEINFO (0)  #define DBG_ENABLE_SERIAL (1) -#define DBG_CYCLE_DELAY (100e3) +#define DBG_CYCLE_DELAY (1e3)  #define DBG_MAX_CYCLES (-1)  // debug print options diff --git a/shared/consts.h b/shared/consts.h index cdd96b3..3f792b4 100644 --- a/shared/consts.h +++ b/shared/consts.h @@ -30,6 +30,11 @@  /** exponential moving average new measurement weight (double 0-1) */  #define W2_EMA_WEIGHT (0.10) +/** minimal time between pings */ +#define W2_PING_FREQUENCY (1e3) +/** max time between ping and answer */ +#define W2_PING_TIMEOUT (5e3) +  /** front-facing distance sensor pinout */  #define W2_FRONT_SENSOR_PIN 5  /** battery voltage sensor pinout */ diff --git a/shared/errcatch.h b/shared/errcatch.h index 7f298c1..a56bc00 100644 --- a/shared/errcatch.h +++ b/shared/errcatch.h @@ -52,6 +52,8 @@ typedef enum {  	W2_E_WARN_SERIAL_NOISY = 0x09 | W2_E_TYPE_WARN,  	/** mode history index out of bounds */  	W2_E_WARN_MODE_HISTORY_BUFFER_IOB = 0x0a | W2_E_TYPE_WARN, +	/** ping timeout reached */ +	W2_E_WARN_PING_TIMEOUT = 0x0b | W2_E_TYPE_WARN,  } w2_e_errorcode;  /**  |