diff options
44 files changed, 740 insertions, 306 deletions
| diff --git a/client/commands.c b/client/commands.c index 778e9c1..d2e53c8 100644 --- a/client/commands.c +++ b/client/commands.c @@ -46,10 +46,21 @@ void w2_send_ping() {  }  void w2_send_mode(w2_e_mode mode) { -	W2_CREATE_MSG_BIN(w2_s_cmd_mode_rx, msg, msg_bin); -	msg->opcode = W2_CMD_MODE | W2_CMDDIR_RX; -	msg->mode	= mode; +	if (mode == W2_M_PREV) { +		W2_CREATE_MSG_BIN(w2_s_cmd_sres_rx, msg, msg_bin); -	w2_send_bin(msg_bin); -	free(msg_bin); +		msg->opcode = W2_CMD_SRES | W2_CMDDIR_RX; +		msg->type	= W2_CMD_SRES_RX_TYPE_PREVMODE; + +		w2_send_bin(msg_bin); +		free(msg_bin); +	} else { +		W2_CREATE_MSG_BIN(w2_s_cmd_mode_rx, msg, msg_bin); + +		msg->opcode = W2_CMD_MODE | W2_CMDDIR_RX; +		msg->mode	= mode; + +		w2_send_bin(msg_bin); +		free(msg_bin); +	}  } diff --git a/client/errcatch.c b/client/errcatch.c index 5e39b00..c39544c 100644 --- a/client/errcatch.c +++ b/client/errcatch.c @@ -1,18 +1,15 @@ -#include "../shared/errcatch.h" +#include <stdlib.h> -void w2_errcatch_handle_error(w2_s_error *error) { -	// TODO: handle more error types -	switch (error->code) { -		case W2_E_WARN_UNCAUGHT_ERROR: { -			break; -		} -		default: { -			g_w2_error_uncaught = true; -#ifdef W2_SIM -			simwarn("Uncaught/unhandled error found with code 0x%02x\n", error->code); -#endif -		} -	} +#include "errcatch.h" -	return; +w2_s_error *g_w2_error_log[W2_ERRCATCH_LOG_SIZE] = {NULL}; +unsigned int g_w2_error_log_index				 = 0; + +void w2_errcatch_log_error(w2_s_error *error) { +	if (g_w2_error_log[g_w2_error_log_index] != NULL) free(g_w2_error_log[g_w2_error_log_index]); +	g_w2_error_log[g_w2_error_log_index] = +		w2_alloc_error(error->code, error->message_length, error->message); +	g_w2_error_log_index = (g_w2_error_log_index + 1) % W2_ERRCATCH_LOG_SIZE;  } + +void w2_errcatch_handle_error(w2_s_error *error) { w2_errcatch_log_error(error); } diff --git a/client/errcatch.h b/client/errcatch.h new file mode 100644 index 0000000..71eb56d --- /dev/null +++ b/client/errcatch.h @@ -0,0 +1,8 @@ +#pragma once + +#include "../shared/errcatch.h" + +#define W2_ERRCATCH_LOG_SIZE 256 + +extern w2_s_error *g_w2_error_log[W2_ERRCATCH_LOG_SIZE]; +extern unsigned int g_w2_error_log_index; diff --git a/client/i18n/en_us.h b/client/i18n/en_us.h index 5547db5..d198296 100644 --- a/client/i18n/en_us.h +++ b/client/i18n/en_us.h @@ -9,6 +9,7 @@  #define W2_UI_BATT_STAT_BATTERY "battery"  #define W2_UI_EXPT_STAT_WARNINGS "warning(s)"  #define W2_UI_EXPT_STAT_ERRORS "error(s)" +  #define W2_UI_MODE_CHRG "charging station"  #define W2_UI_MODE_DIRC "direct control"  #define W2_UI_MODE_GRID "grid" @@ -17,3 +18,98 @@  #define W2_UI_MODE_MAZE "maze"  #define W2_UI_MODE_SCAL "sensor calibration"  #define W2_UI_MODE_SPIN "wet floor simulation" + +#define W2_UI_TAB_LABEL_START "info" +#define W2_UI_TAB_LABEL_DIRC "direct control" +#define W2_UI_TAB_LABEL_ERRCATCH "logs" +#define W2_UI_TAB_LABEL_MCFG "map" +#define W2_UI_TAB_LABEL_ORDERS "orders" +#define W2_UI_TAB_LABEL_MODES "set mode" + +#define W2_UI_TAB_START_MESSAGE "" \ +	"welcome to the wall-e2 console application!\n" \ +	"this is client version " W2_BUILD_STR "\n" \ +	"\n" \ +	"this application is functionally similar to a BIOS.\n" \ +	"here's a brief summary of keyboard commands:\n" \ +	"\n" \ +	"<tab>        switch to next tab\n" \ +	"<ctrl-c>     exit\n" \ +	"\n" \ + +#define W2_UI_ERROR_SEVERITY_CRIT "CRIT" +#define W2_UI_ERROR_SEVERITY_WARN "WARN" +#define W2_UI_ERROR_SEVERITY_INFO "INFO" +#define W2_UI_ERROR_SEVERITY_VERB "VERB" + +#define W2_UI_ERROR_INT_W2_E_UNKNOWN "W2_E_UNKNOWN" +#define W2_UI_ERROR_INT_W2_E_CRIT_CONN_LOST "W2_E_CRIT_CONN_LOST" +#define W2_UI_ERROR_INT_W2_E_CRIT_COM_UNAVAILABLE "W2_E_CRIT_COM_UNAVAILABLE" +#define W2_UI_ERROR_INT_W2_E_CRIT_LINE_LOST "W2_E_CRIT_LINE_LOST" +#define W2_UI_ERROR_INT_W2_E_CRIT_OBSTACLE_STUCK "W2_E_CRIT_OBSTACLE_STUCK" +#define W2_UI_ERROR_INT_W2_E_CRIT_VERSION_INCOMPATIBLE "W2_E_CRIT_VERSION_INCOMPATIBLE" +#define W2_UI_ERROR_INT_W2_E_WARN_BATTERY_LOW "W2_E_WARN_BATTERY_LOW" +#define W2_UI_ERROR_INT_W2_E_WARN_OBSTACLE_DETECTED "W2_E_WARN_OBSTACLE_DETECTED" +#define W2_UI_ERROR_INT_W2_E_WARN_CYCLE_EXPIRED "W2_E_WARN_CYCLE_EXPIRED" +#define W2_UI_ERROR_INT_W2_E_WARN_UNCAUGHT_ERROR "W2_E_WARN_UNCAUGHT_ERROR" +#define W2_UI_ERROR_INT_W2_E_WARN_ERR_BUFFER_FULL "W2_E_WARN_ERR_BUFFER_FULL" +#define W2_UI_ERROR_INT_W2_E_WARN_LINE_LOST "W2_E_WARN_LINE_LOST" +#define W2_UI_ERROR_INT_W2_E_WARN_SERCOMM_BUFFER_FULL "W2_E_WARN_SERCOMM_BUFFER_FULL" +#define W2_UI_ERROR_INT_W2_E_WARN_VERSION_INCOMPATIBLE "W2_E_WARN_VERSION_INCOMPATIBLE" +#define W2_UI_ERROR_INT_W2_E_WARN_SERIAL_NOISY "W2_E_WARN_SERIAL_NOISY" +#define W2_UI_ERROR_INT_W2_E_WARN_MODE_HISTORY_BUFFER_IOB "W2_E_WARN_MODE_HISTORY_BUFFER_IOB" +#define W2_UI_ERROR_INT_W2_E_WARN_PING_TIMEOUT "W2_E_WARN_PING_TIMEOUT" + +#define W2_UI_ERROR_USR_W2_E_UNKNOWN "unknown error code" +#define W2_UI_ERROR_USR_W2_E_CRIT_CONN_LOST "connection to robot lost" +#define W2_UI_ERROR_USR_W2_E_CRIT_COM_UNAVAILABLE "COM-port unavailable" +#define W2_UI_ERROR_USR_W2_E_CRIT_LINE_LOST "line lost and unable to be found automatically" +#define W2_UI_ERROR_USR_W2_E_CRIT_OBSTACLE_STUCK "obstacle detected, robot stuck" +#define W2_UI_ERROR_USR_W2_E_CRIT_VERSION_INCOMPATIBLE "major version mismatch detected, please update robot" +#define W2_UI_ERROR_USR_W2_E_WARN_BATTERY_LOW "battery low, going to charging station" +#define W2_UI_ERROR_USR_W2_E_WARN_OBSTACLE_DETECTED "obstacle detected, waiting" +#define W2_UI_ERROR_USR_W2_E_WARN_CYCLE_EXPIRED "maximum logic module cycle time exceeded" +#define W2_UI_ERROR_USR_W2_E_WARN_UNCAUGHT_ERROR "uncaught error occurred" +#define W2_UI_ERROR_USR_W2_E_WARN_ERR_BUFFER_FULL "error buffer full" +#define W2_UI_ERROR_USR_W2_E_WARN_LINE_LOST "line lost, trying to find line automatically" +#define W2_UI_ERROR_USR_W2_E_WARN_SERCOMM_BUFFER_FULL "serial communication buffer full" +#define W2_UI_ERROR_USR_W2_E_WARN_VERSION_INCOMPATIBLE "minor version mismatch detected, this might cause problems" +#define W2_UI_ERROR_USR_W2_E_WARN_SERIAL_NOISY "invalid serial data received (noisy channel / check connection?)" +#define W2_UI_ERROR_USR_W2_E_WARN_MODE_HISTORY_BUFFER_IOB "mode history buffer index out of bounds" +#define W2_UI_ERROR_USR_W2_E_WARN_PING_TIMEOUT "ping timed out" + +#define W2_UI_ORDER_CMD_HELP "help" +#define W2_UI_ORDER_CMD_START "start" +#define W2_UI_ORDER_CMD_COORDINATE "coordinate" +#define W2_UI_ORDER_CMD_DONE "done" +#define W2_UI_ORDER_CMD_SEND "send" + +#define W2_UI_ORDER_MSG_ERROR "unknown command, type 'help' to see a list of valid commands\n\n" +#define W2_UI_ORDER_MSG_HELP \ +	"commands:\n" \ +	"\n" \ +	W2_UI_ORDER_CMD_HELP ": print this list\n" \ +	W2_UI_ORDER_CMD_START ": start an order\n" \ +	W2_UI_ORDER_CMD_COORDINATE " <x> <y>: add a coordinate to the current order\n" \ +	W2_UI_ORDER_CMD_DONE ": finish the current order\n" \ +	W2_UI_ORDER_CMD_SEND ": send the latest completed order to robot\n\n" +#define W2_UI_ORDER_MSG_ORDER_START_OK "order started\n\n" +#define W2_UI_ORDER_MSG_ORDER_START_ERR "order already started\n\n" +#define W2_UI_ORDER_MSG_ORDER_APPEND_OK "appended coordinate to order\n\n" +#define W2_UI_ORDER_MSG_ORDER_APPEND_ERR "no order active\n\n" +#define W2_UI_ORDER_MSG_ORDER_DONE_OK "order saved\n\n" +#define W2_UI_ORDER_MSG_ORDER_DONE_ERR "no order active\n\n" +#define W2_UI_ORDER_MSG_ORDER_SENT "order sent to robot\n\n" + +#define W2_UI_MODES_INFO \ +	"press keys (0-9) for:\n" \ +	"\n" \ +	"1 - set to maze mode\n" \ +	"2 - set to grid mode\n" \ +	"3 - halt (emergency stop)\n" \ +	"4 - set to charging station mode\n" \ +	"5 - set to spinning mode (wet floor simulation)\n" \ +	"6 - calibrate sensors\n" \ +	"\n" \ +	"0 - previous\n" \ + diff --git a/client/main.c b/client/main.c index b5af0e8..4d7f484 100644 --- a/client/main.c +++ b/client/main.c @@ -7,7 +7,11 @@  #include "time.h"  #include "ui.h" -w2_s_client_state g_w2_state = {.ping_received = true}; +w2_s_client_state g_w2_state = { +	.ping_received = true, +	.map_height	   = W2_MAP_DEFAULT_HEIGHT, +	.map_width	   = W2_MAP_DEFAULT_WIDTH, +};  int main(int argc, char **argv) {  	w2_client_setup(argc, argv); diff --git a/client/main.h b/client/main.h index cc4c728..b72b507 100644 --- a/client/main.h +++ b/client/main.h @@ -13,8 +13,10 @@ typedef struct {  	uint8_t mode; +	uint8_t map_width; +	uint8_t map_height; +  	w2_s_cmd_info_tx info; -	w2_s_cmd_sens_tx io;  } w2_s_client_state;  extern w2_s_client_state g_w2_state; diff --git a/client/serial.c b/client/serial.c index 112fd81..2a4d26f 100644 --- a/client/serial.c +++ b/client/serial.c @@ -3,6 +3,7 @@  #include "../shared/protocol.h"  #include "../shared/serial_parse.h"  #include "commands.h" +#include "errcatch.h"  #include "main.h"  #include "serial.h"  #include "time.h" @@ -26,14 +27,17 @@ void w2_cmd_ping_rx(w2_s_bin *data) {  void w2_cmd_ping_tx(w2_s_bin *data) { w2_send_bin(data); } -void w2_cmd_expt_tx(w2_s_bin *data) {} +void w2_cmd_expt_tx(w2_s_bin *data) { +	W2_CAST_BIN(w2_s_cmd_expt_tx, data, cast); +	w2_errcatch_throw_msg(cast->error, cast->length, (char *)cast->message); +} +  void w2_cmd_mode_tx(w2_s_bin *data) {  	W2_CAST_BIN(w2_s_cmd_mode_tx, data, cast);  	g_w2_state.mode = cast->mode;  }  void w2_cmd_cord_tx(w2_s_bin *data) {}  void w2_cmd_bomd_tx(w2_s_bin *data) {} -void w2_cmd_sens_tx(w2_s_bin *data) {}  void w2_cmd_info_tx(w2_s_bin *data) {  	memcpy(&g_w2_state.info, data->data, sizeof(w2_s_cmd_info_tx)); @@ -46,7 +50,6 @@ void w2_cmd_cord_rx(w2_s_bin *data) { return; }  void w2_cmd_bomd_rx(w2_s_bin *data) { return; }  void w2_cmd_sres_rx(w2_s_bin *data) { return; }  void w2_cmd_mcfg_rx(w2_s_bin *data) { return; } -void w2_cmd_sens_rx(w2_s_bin *data) { return; }  void w2_cmd_info_rx(w2_s_bin *data) { return; }  void w2_cmd_disp_rx(w2_s_bin *data) { return; }  void w2_cmd_play_rx(w2_s_bin *data) { return; } diff --git a/client/serial_win32.c b/client/serial_win32.c index edc9db1..99f4160 100644 --- a/client/serial_win32.c +++ b/client/serial_win32.c @@ -2,20 +2,12 @@  #include "serial.h" -int w2_serial_read() { -    return 0x00; -} +int w2_serial_read() { return 0x00; } -bool w2_serial_write(char *data, uint8_t length) { -    return true; -} +bool w2_serial_write(char *data, uint8_t length) { return true; } -bool w2_serial_open(const char *port_name) { -    return true; -} +bool w2_serial_open(const char *port_name) { return true; } -void w2_serial_close() { -    return; -} +void w2_serial_close() { return; }  #endif diff --git a/client/setup.c b/client/setup.c index fd37c13..43ed135 100644 --- a/client/setup.c +++ b/client/setup.c @@ -33,12 +33,23 @@ void w2_client_setup(int argc, char **argv) {  	noecho();  	curs_set(false);  	nodelay(g_w2_ui_win, true); +	keypad(g_w2_ui_win, true);  	w2_strings_init();  	w2_cmd_setup_handlers(); +	w2_ui_tabbar_init();  	w2_send_info(); +	g_w2_ui_width  = getmaxx(g_w2_ui_win); +	g_w2_ui_height = getmaxy(g_w2_ui_win); + +	g_w2_ui_pad_tabbar	  = newpad(1, g_w2_ui_width); +	g_w2_ui_pad_body	  = newpad(g_w2_ui_height - 5, g_w2_ui_width); +	g_w2_ui_pad_statusbar = newpad(2, g_w2_ui_width); +	g_w2_ui_pad_seperator = newpad(1, g_w2_ui_width + 1); +	scrollok(g_w2_ui_pad_body, true); +  	// check endianness  	g_w2_endianness = *_ptest;  } diff --git a/client/strings.c b/client/strings.c index b97d4b2..1354653 100644 --- a/client/strings.c +++ b/client/strings.c @@ -1,16 +1,93 @@  #include "strings.h" +#include "../shared/errcatch.h"  char *g_w2_mode_strings[W2_MODE_COUNT]; +char *g_w2_tab_strings[W2_UI_TAB_COUNT]; +char *g_w2_error_type_strings[4]; +char *g_w2_error_internal_strings[0x100]; +char *g_w2_error_user_strings[0x100];  void w2_strings_modes_init() {  	g_w2_mode_strings[W2_M_CHRG] = W2_UI_MODE_CHRG;  	g_w2_mode_strings[W2_M_DIRC] = W2_UI_MODE_DIRC;  	g_w2_mode_strings[W2_M_GRID] = W2_UI_MODE_GRID;  	g_w2_mode_strings[W2_M_HALT] = W2_UI_MODE_HALT; -	g_w2_mode_strings[W2_M_LCAL] = W2_UI_MODE_LCAL;  	g_w2_mode_strings[W2_M_MAZE] = W2_UI_MODE_MAZE;  	g_w2_mode_strings[W2_M_SCAL] = W2_UI_MODE_SCAL;  	g_w2_mode_strings[W2_M_SPIN] = W2_UI_MODE_SPIN;  } -void w2_strings_init() { w2_strings_modes_init(); } +void w2_strings_tabs_init() { +	g_w2_tab_strings[W2_UI_TAB_START]	 = W2_UI_TAB_LABEL_START; +	g_w2_tab_strings[W2_UI_TAB_ERRCATCH] = W2_UI_TAB_LABEL_ERRCATCH; +	g_w2_tab_strings[W2_UI_TAB_DIRC]	 = W2_UI_TAB_LABEL_DIRC; +	g_w2_tab_strings[W2_UI_TAB_ORDERS]	 = W2_UI_TAB_LABEL_ORDERS; +	g_w2_tab_strings[W2_UI_TAB_MODES]	 = W2_UI_TAB_LABEL_MODES; +} + +void w2_strings_errors_types() { +	g_w2_error_type_strings[0b00] = W2_UI_ERROR_SEVERITY_CRIT; +	g_w2_error_type_strings[0b01] = W2_UI_ERROR_SEVERITY_WARN; +	g_w2_error_type_strings[0b10] = W2_UI_ERROR_SEVERITY_INFO; +	g_w2_error_type_strings[0b11] = W2_UI_ERROR_SEVERITY_VERB; +} + +void w2_strings_errors_internal() { +	g_w2_error_internal_strings[W2_E_CRIT_CONN_LOST] = W2_UI_ERROR_INT_W2_E_CRIT_CONN_LOST; +	g_w2_error_internal_strings[W2_E_CRIT_COM_UNAVAILABLE] = +		W2_UI_ERROR_INT_W2_E_CRIT_COM_UNAVAILABLE; +	g_w2_error_internal_strings[W2_E_CRIT_LINE_LOST] = W2_UI_ERROR_INT_W2_E_CRIT_LINE_LOST; +	g_w2_error_internal_strings[W2_E_CRIT_OBSTACLE_STUCK] = +		W2_UI_ERROR_INT_W2_E_CRIT_OBSTACLE_STUCK; +	g_w2_error_internal_strings[W2_E_CRIT_VERSION_INCOMPATIBLE] = +		W2_UI_ERROR_INT_W2_E_CRIT_VERSION_INCOMPATIBLE; +	g_w2_error_internal_strings[W2_E_WARN_BATTERY_LOW] = W2_UI_ERROR_INT_W2_E_WARN_BATTERY_LOW; +	g_w2_error_internal_strings[W2_E_WARN_OBSTACLE_DETECTED] = +		W2_UI_ERROR_INT_W2_E_WARN_OBSTACLE_DETECTED; +	g_w2_error_internal_strings[W2_E_WARN_CYCLE_EXPIRED] = W2_UI_ERROR_INT_W2_E_WARN_CYCLE_EXPIRED; +	g_w2_error_internal_strings[W2_E_WARN_UNCAUGHT_ERROR] = +		W2_UI_ERROR_INT_W2_E_WARN_UNCAUGHT_ERROR; +	g_w2_error_internal_strings[W2_E_WARN_ERR_BUFFER_FULL] = +		W2_UI_ERROR_INT_W2_E_WARN_ERR_BUFFER_FULL; +	g_w2_error_internal_strings[W2_E_WARN_LINE_LOST] = W2_UI_ERROR_INT_W2_E_WARN_LINE_LOST; +	g_w2_error_internal_strings[W2_E_WARN_SERCOMM_BUFFER_FULL] = +		W2_UI_ERROR_INT_W2_E_WARN_SERCOMM_BUFFER_FULL; +	g_w2_error_internal_strings[W2_E_WARN_VERSION_INCOMPATIBLE] = +		W2_UI_ERROR_INT_W2_E_WARN_VERSION_INCOMPATIBLE; +	g_w2_error_internal_strings[W2_E_WARN_SERIAL_NOISY] = W2_UI_ERROR_INT_W2_E_WARN_SERIAL_NOISY; +	g_w2_error_internal_strings[W2_E_WARN_MODE_HISTORY_BUFFER_IOB] = +		W2_UI_ERROR_INT_W2_E_WARN_MODE_HISTORY_BUFFER_IOB; +	g_w2_error_internal_strings[W2_E_WARN_PING_TIMEOUT] = W2_UI_ERROR_INT_W2_E_WARN_PING_TIMEOUT; +} + +void w2_strings_errors_user() { +	g_w2_error_user_strings[W2_E_CRIT_CONN_LOST]	   = W2_UI_ERROR_USR_W2_E_CRIT_CONN_LOST; +	g_w2_error_user_strings[W2_E_CRIT_COM_UNAVAILABLE] = W2_UI_ERROR_USR_W2_E_CRIT_COM_UNAVAILABLE; +	g_w2_error_user_strings[W2_E_CRIT_LINE_LOST]	   = W2_UI_ERROR_USR_W2_E_CRIT_LINE_LOST; +	g_w2_error_user_strings[W2_E_CRIT_OBSTACLE_STUCK]  = W2_UI_ERROR_USR_W2_E_CRIT_OBSTACLE_STUCK; +	g_w2_error_user_strings[W2_E_CRIT_VERSION_INCOMPATIBLE] = +		W2_UI_ERROR_USR_W2_E_CRIT_VERSION_INCOMPATIBLE; +	g_w2_error_user_strings[W2_E_WARN_BATTERY_LOW] = W2_UI_ERROR_USR_W2_E_WARN_BATTERY_LOW; +	g_w2_error_user_strings[W2_E_WARN_OBSTACLE_DETECTED] = +		W2_UI_ERROR_USR_W2_E_WARN_OBSTACLE_DETECTED; +	g_w2_error_user_strings[W2_E_WARN_CYCLE_EXPIRED]   = W2_UI_ERROR_USR_W2_E_WARN_CYCLE_EXPIRED; +	g_w2_error_user_strings[W2_E_WARN_UNCAUGHT_ERROR]  = W2_UI_ERROR_USR_W2_E_WARN_UNCAUGHT_ERROR; +	g_w2_error_user_strings[W2_E_WARN_ERR_BUFFER_FULL] = W2_UI_ERROR_USR_W2_E_WARN_ERR_BUFFER_FULL; +	g_w2_error_user_strings[W2_E_WARN_LINE_LOST]	   = W2_UI_ERROR_USR_W2_E_WARN_LINE_LOST; +	g_w2_error_user_strings[W2_E_WARN_SERCOMM_BUFFER_FULL] = +		W2_UI_ERROR_USR_W2_E_WARN_SERCOMM_BUFFER_FULL; +	g_w2_error_user_strings[W2_E_WARN_VERSION_INCOMPATIBLE] = +		W2_UI_ERROR_USR_W2_E_WARN_VERSION_INCOMPATIBLE; +	g_w2_error_user_strings[W2_E_WARN_SERIAL_NOISY] = W2_UI_ERROR_USR_W2_E_WARN_SERIAL_NOISY; +	g_w2_error_user_strings[W2_E_WARN_MODE_HISTORY_BUFFER_IOB] = +		W2_UI_ERROR_USR_W2_E_WARN_MODE_HISTORY_BUFFER_IOB; +	g_w2_error_user_strings[W2_E_WARN_PING_TIMEOUT] = W2_UI_ERROR_USR_W2_E_WARN_PING_TIMEOUT; +} + +void w2_strings_init() { +	w2_strings_errors_types(); +	w2_strings_errors_internal(); +	w2_strings_errors_user(); +	w2_strings_modes_init(); +	w2_strings_tabs_init(); +} diff --git a/client/strings.h b/client/strings.h index 0085228..5d20b8e 100644 --- a/client/strings.h +++ b/client/strings.h @@ -2,9 +2,12 @@  #include "../shared/modes.h"  #include "i18n.h" - -#define W2_STRINGS_MODE_MAP_BUFFER_SIZE 32 +#include "ui.h"  extern char *g_w2_mode_strings[W2_MODE_COUNT]; +extern char *g_w2_tab_strings[W2_UI_TAB_COUNT]; +extern char *g_w2_error_type_strings[4]; +extern char *g_w2_error_internal_strings[0x100]; +extern char *g_w2_error_user_strings[0x100];  void w2_strings_init(); diff --git a/client/time_windows.c b/client/time_windows.c index f9082d6..76d1879 100644 --- a/client/time_windows.c +++ b/client/time_windows.c @@ -2,9 +2,7 @@  #include "time.h" -unsigned long w2_get_time() { -	return 0; -} +unsigned long w2_get_time() { return 0; }  void w2_timer_start(w2_e_client_timers label) { g_w2_client_timers[label] = w2_get_time(); } diff --git a/client/ui.c b/client/ui.c index f636501..cdf2f3b 100644 --- a/client/ui.c +++ b/client/ui.c @@ -11,61 +11,94 @@  #include "ui.h"  WINDOW *g_w2_ui_win; -unsigned int g_w2_ui_width				= 0; -unsigned int g_w2_ui_height				= 0; -void (*g_w2_ui_current_tab)(bool first) = &w2_ui_dirc; -void (*g_w2_ui_last_tab)(bool first)	= NULL; +WINDOW *g_w2_ui_pad_tabbar; +WINDOW *g_w2_ui_pad_statusbar; +WINDOW *g_w2_ui_pad_seperator; +WINDOW *g_w2_ui_pad_body; +int g_w2_ui_pad_body_scroll		 = 0; +unsigned int g_w2_ui_width		 = 0; +unsigned int g_w2_ui_height		 = 0; +w2_e_ui_tabs g_w2_ui_current_tab = W2_UI_TAB_START; +w2_e_ui_tabs g_w2_ui_last_tab; + +void w2_wmvaddstr(WINDOW *win, unsigned int y, unsigned int x, char *str) { +	wmove(win, y, x); +	waddstr(win, str); +} + +void w2_wmvaddnstr(WINDOW *win, unsigned int y, unsigned int x, char *str, unsigned int len) { +	wmove(win, y, x); +	waddnstr(win, str, len); +} + +void w2_ui_switch_tab(w2_e_ui_tabs next_tab) { +	g_w2_ui_current_tab = next_tab % W2_UI_TAB_COUNT; +	wclear(g_w2_ui_pad_body); +	curs_set(false); +} + +void w2_ui_key_handler() { +	int ch; +	void (*current_mode_key_handler)() = g_w2_keyhndl_ptrs[g_w2_ui_current_tab]; +	while ((ch = getch()) != -1) { +		if (ch == '\t') +			w2_ui_switch_tab(g_w2_ui_current_tab + 1); +		else if (current_mode_key_handler != NULL) +			(*current_mode_key_handler)(ch); +	} +}  void w2_ui_main() {  	g_w2_ui_width  = getmaxx(g_w2_ui_win);  	g_w2_ui_height = getmaxy(g_w2_ui_win); +	w2_ui_key_handler();  	w2_ui_paint();  }  void w2_ui_paint() {  	w2_ui_paint_statusbar(); +	w2_ui_paint_tabbar(); +	w2_ui_paint_seperator();  	if (w2_timer_end(W2_TIMER_UPDATE) >= (1000 / W2_UI_UPDATE_FPS)) { -		(*g_w2_ui_current_tab)(g_w2_ui_last_tab != g_w2_ui_current_tab); +		(*g_w2_tab_ptrs[g_w2_ui_current_tab])(g_w2_ui_last_tab != g_w2_ui_current_tab);  		g_w2_ui_last_tab = g_w2_ui_current_tab;  		w2_timer_start(W2_TIMER_UPDATE);  	} -	refresh(); +	prefresh(g_w2_ui_pad_statusbar, 0, 0, 0, 0, 1, g_w2_ui_width - 1); +	prefresh(g_w2_ui_pad_tabbar, 0, 0, 2, 0, 2, g_w2_ui_width - 1); +	prefresh(g_w2_ui_pad_seperator, 0, 0, 3, 0, 3, g_w2_ui_width - 1); +	prefresh(g_w2_ui_pad_body, W2_MAX(0, g_w2_ui_pad_body_scroll), 0, +			 4 - W2_MIN(0, g_w2_ui_pad_body_scroll), 0, g_w2_ui_height - 2, g_w2_ui_width - 1);  }  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); +	for (int i = 0; i < g_w2_ui_width; i++) temp[i] = ' '; +	w2_wmvaddnstr(g_w2_ui_pad_statusbar, 0, 0, temp, g_w2_ui_width); +	w2_wmvaddnstr(g_w2_ui_pad_statusbar, 1, 0, temp, g_w2_ui_width); -	g_w2_state.connected -		? sprintf(temp,  W2_UI_CONN_STAT_CONNECTED ", %ims %s", g_w2_state.ping, W2_UI_CONN_STAT_PING) -		: sprintf(temp, W2_UI_CONN_STAT_DISCONNECTED); -	mvaddstr(0, 0, temp); +	g_w2_state.connected ? sprintf(temp, W2_UI_CONN_STAT_CONNECTED ", %ims %s", g_w2_state.ping, +								   W2_UI_CONN_STAT_PING) +						 : sprintf(temp, W2_UI_CONN_STAT_DISCONNECTED); +	w2_wmvaddstr(g_w2_ui_pad_statusbar, 0, 0, temp);  	sprintf(temp, "(%s)", g_w2_state.info.build_str); -	mvaddstr(0, g_w2_ui_width / 2 - strlen(temp) / 2, temp); +	w2_wmvaddstr(g_w2_ui_pad_statusbar, 0, g_w2_ui_width / 2 - strlen(temp) / 2, temp);  	sprintf(temp, "%s %i%%", W2_UI_BATT_STAT_BATTERY, g_w2_state.battery_level); -	mvaddstr(0, g_w2_ui_width - strlen(temp), temp); +	w2_wmvaddstr(g_w2_ui_pad_statusbar, 0, g_w2_ui_width - strlen(temp), temp);  	sprintf(temp, "[%s]", g_w2_mode_strings[g_w2_state.mode]); -	mvaddstr(1, 0, temp); +	w2_wmvaddstr(g_w2_ui_pad_statusbar, 1, 0, temp);  	sprintf(temp, "%i %s, %i %s", 0, W2_UI_EXPT_STAT_WARNINGS, 0, W2_UI_EXPT_STAT_ERRORS); -	mvaddstr(1, g_w2_ui_width - strlen(temp), temp); - -	w2_ui_paint_tabbar(); - -	for (unsigned int i = 0; i < g_w2_ui_width; i++) temp[i] = '-'; -	mvaddnstr(3, 0, temp, g_w2_ui_width); +	w2_wmvaddstr(g_w2_ui_pad_statusbar, 1, g_w2_ui_width - strlen(temp), temp);  } -void w2_ui_paint_tabbar() { +void w2_ui_paint_seperator() {  	char temp[g_w2_ui_width]; -	sprintf(temp, "-- tab bar here --"); -	mvaddstr(2, g_w2_ui_width / 2 - strlen(temp) / 2, temp); +	for (unsigned int i = 0; i < g_w2_ui_width; i++) temp[i] = '-'; +	w2_wmvaddnstr(g_w2_ui_pad_seperator, 0, 0, temp, g_w2_ui_width - 1);  } diff --git a/client/ui.h b/client/ui.h index 0d375de..c169401 100644 --- a/client/ui.h +++ b/client/ui.h @@ -3,12 +3,34 @@  #include <ncurses.h>  #include <stdint.h> -#define W2_UI_UPDATE_FPS (60) +#define W2_UI_UPDATE_FPS 60 +/** order tab current command buffer (char[]) */ +#define W2_UI_ORDER_CMD_BUFFER_SIZE 80 +/** order tab current command buffer (uint16_t[]) */ +#define W2_UI_ORDER_BUFFER_SIZE 16 + +#define W2_UI_TAB_COUNT 5 +typedef enum { +	W2_UI_TAB_START	   = 0, +	W2_UI_TAB_ERRCATCH = 1, +	W2_UI_TAB_DIRC	   = 2, +	W2_UI_TAB_ORDERS   = 3, +	W2_UI_TAB_MODES	   = 4, +} w2_e_ui_tabs;  extern WINDOW *g_w2_ui_win; +extern WINDOW *g_w2_ui_pad_tabbar; +extern WINDOW *g_w2_ui_pad_statusbar; +extern WINDOW *g_w2_ui_pad_seperator; +extern WINDOW *g_w2_ui_pad_body; +extern int g_w2_ui_pad_body_scroll;  extern unsigned int g_w2_ui_width;  extern unsigned int g_w2_ui_height; -extern void (*g_w2_ui_current_tab)(bool first); +extern void (*g_w2_tab_ptrs[W2_UI_TAB_COUNT])(bool first); +extern void (*g_w2_keyhndl_ptrs[W2_UI_TAB_COUNT])(int key); +extern w2_e_ui_tabs g_w2_ui_current_tab; + +void w2_ui_switch_tab(w2_e_ui_tabs next_tab);  /** update terminal props */  void w2_ui_update(); @@ -23,5 +45,20 @@ void w2_ui_main();  void w2_ui_paint_statusbar();  /** draw tab bar */  void w2_ui_paint_tabbar(); +/** draw seperator under tab bar */ +void w2_ui_paint_seperator(); + +void w2_ui_tabbar_init(); + +void w2_ui_tab_dirc(bool first); +void w2_ui_tab_start(bool first); +void w2_ui_tab_errcatch(bool first); +void w2_ui_tab_modes(bool first); +void w2_ui_tab_orders(bool first); +void w2_ui_onkey_dirc(int ch); +void w2_ui_onkey_errcatch(int ch); +void w2_ui_onkey_modes(int ch); +void w2_ui_onkey_orders(int ch); -void w2_ui_dirc(bool first); +void w2_wmvaddstr(WINDOW *win, unsigned int y, unsigned int x, char *str); +void w2_wmvaddnstr(WINDOW *win, unsigned int y, unsigned int x, char *str, unsigned int len); diff --git a/client/ui_dirc.c b/client/ui_dirc.c index ed69cd2..db91661 100644 --- a/client/ui_dirc.c +++ b/client/ui_dirc.c @@ -1,8 +1,14 @@  #include "../shared/protocol.h"  #include "../shared/util.h"  #include "commands.h" +#include "errcatch.h"  #include "ui.h" +unsigned int g_w2_lb = 0; +unsigned int g_w2_lf = 0; +unsigned int g_w2_rb = 0; +unsigned int g_w2_rf = 0; +  /** decay modifier */  #define W2_DIRC_MOD ((double)0.95)  /** add value per key press */ @@ -50,7 +56,7 @@ void w2_ui_bar_graph(unsigned int y, unsigned int x, unsigned int width, double  	temp[width - 1] = '|';  	for (unsigned int i = 0; i < width - 2; i++) temp[i + 1] = i < width * value ? '*' : ' '; -	mvaddnstr(y, x, temp, width); +	w2_wmvaddnstr(g_w2_ui_pad_body, y, x, temp, width);  }  void w2_ui_bar_graph_pm(unsigned int y, unsigned int x, unsigned int width, double value) { @@ -67,46 +73,48 @@ void w2_ui_bar_graph_pm(unsigned int y, unsigned int x, unsigned int width, doub  			temp[i + 1] = i > hw ? ' ' : (hw - i) < -(hw * value) ? '*' : ' ';  	} -	mvaddnstr(y, x, temp, width + 2); +	w2_wmvaddnstr(g_w2_ui_pad_body, y, x, temp, width + 2);  }  void w2_ui_dirc_paint(int left, int right) { -	mvaddstr(4, 0, "left drive:  "); -	w2_ui_bar_graph_pm(4, 13, g_w2_ui_width - 13, (double)left / 255); -	mvaddstr(5, 0, "right drive: "); -	w2_ui_bar_graph_pm(5, 13, g_w2_ui_width - 13, (double)right / 255); - -	mvaddstr(7, 0, -			 "             controls:\n" -			 "\n" -			 " <q>      <w>       <e>   forward\n" -			 " <a>      <s>       <d>   backward\n" -			 "left     both      right\n" -			 "\n" -			 "<space> send dirc mode command"); +	w2_wmvaddstr(g_w2_ui_pad_body, 0, 0, "left drive:  "); +	w2_ui_bar_graph_pm(0, 13, g_w2_ui_width - 13, (double)left / 255); +	w2_wmvaddstr(g_w2_ui_pad_body, 1, 0, "right drive: "); +	w2_ui_bar_graph_pm(1, 13, g_w2_ui_width - 13, (double)right / 255); + +	w2_wmvaddstr(g_w2_ui_pad_body, 3, 0, +				 "             controls:\n" +				 "\n" +				 " <q>      <w>       <e>   forward\n" +				 " <a>      <s>       <d>   backward\n" +				 "left     both      right\n" +				 "\n" +				 "<space> send dirc mode command"); +} + +void w2_ui_onkey_dirc(int ch) { +	if (ch == 'e' || ch == 'w') g_w2_lf++; +	if (ch == 'd' || ch == 's') g_w2_lb++; +	if (ch == 'q' || ch == 'w') g_w2_rf++; +	if (ch == 'a' || ch == 's') g_w2_rb++; +	if (ch == ' ') w2_send_mode(W2_M_DIRC);  } -void w2_ui_dirc(bool first) { +void w2_ui_tab_dirc(bool first) { +	g_w2_ui_pad_body_scroll = 0;  	if (first) w2_ui_dirc_init(); -	int ch			= 0; -	unsigned int lb = 0; -	unsigned int lf = 0; -	unsigned int rb = 0; -	unsigned int rf = 0; -	while ((ch = getch()) != -1) { -		if (ch == 'e' || ch == 'w') lf++; -		if (ch == 'd' || ch == 's') lb++; -		if (ch == 'q' || ch == 'w') rf++; -		if (ch == 'a' || ch == 's') rb++; -		if (ch == ' ') w2_send_mode(W2_M_DIRC); -	} -	int drive_l = w2_dirc_motor_l(lf, lb); -	int drive_r = w2_dirc_motor_r(rf, rb); +	int drive_l = w2_dirc_motor_l(g_w2_lf, g_w2_lb); +	int drive_r = w2_dirc_motor_r(g_w2_rf, g_w2_rb);  	drive_l += drive_r * W2_DIRC_STP;  	drive_r += drive_l * W2_DIRC_STP;  	w2_send_dirc(drive_l, drive_r);  	w2_ui_dirc_paint(drive_l, drive_r); + +	g_w2_lb = 0; +	g_w2_lf = 0; +	g_w2_rb = 0; +	g_w2_rf = 0;  } diff --git a/client/ui_errcatch.c b/client/ui_errcatch.c new file mode 100644 index 0000000..5d5365f --- /dev/null +++ b/client/ui_errcatch.c @@ -0,0 +1,49 @@ +#include <stdlib.h> +#include <string.h> + +#include "../shared/util.h" +#include "errcatch.h" +#include "i18n.h" +#include "strings.h" +#include "ui.h" + +unsigned int g_w2_errcatch_log_line = 0; + +char *w2_err_format(w2_s_error *error) { +	const char *type	 = g_w2_error_type_strings[error->code >> 6]; +	const char *internal = g_w2_error_internal_strings[error->code]; +	const char *user	 = g_w2_error_user_strings[error->code]; +	if (internal == NULL || user == NULL) { +		internal = W2_UI_ERROR_INT_W2_E_UNKNOWN; +		user	 = W2_UI_ERROR_USR_W2_E_UNKNOWN; +	} +	size_t errdesc_len = strlen(type) + strlen(internal) + strlen(user) + 8; +	size_t msg_indent  = strlen(type) + 3; +	char *ret_str	   = malloc( +			 errdesc_len + (error->message_length > 0 ? error->message_length + msg_indent : 0) + 1); +	sprintf(ret_str, "[%s] %02x#%s: %s", type, error->code, internal, user); +	if (error->message_length > 0) { +		sprintf(ret_str + errdesc_len, "\n%*c%s", (int)msg_indent, ' ', error->message); +		g_w2_errcatch_log_line += 1 + w2_newline_count(error->message, error->message_length); +	} +	return ret_str; +} + +void w2_ui_onkey_errcatch(int ch) {} + +void w2_ui_tab_errcatch(bool first) { +	g_w2_errcatch_log_line	= 0; +	g_w2_ui_pad_body_scroll = 5 - g_w2_ui_height; +	for (unsigned int x = 0; x < W2_ERRCATCH_LOG_SIZE; x++) { +		unsigned int i = (x + g_w2_error_log_index) % W2_ERRCATCH_LOG_SIZE; +		if (g_w2_error_log[i] == NULL) continue; + +		wmove(g_w2_ui_pad_body, g_w2_errcatch_log_line, 0); +		char *err_str = w2_err_format(g_w2_error_log[i]); +		waddstr(g_w2_ui_pad_body, err_str); +		free(err_str); + +		g_w2_errcatch_log_line++; +	} +	g_w2_ui_pad_body_scroll += g_w2_errcatch_log_line; +} diff --git a/client/ui_modes.c b/client/ui_modes.c new file mode 100644 index 0000000..3048ba9 --- /dev/null +++ b/client/ui_modes.c @@ -0,0 +1,16 @@ +#include "commands.h" +#include "i18n.h" +#include "ui.h" + +void w2_ui_onkey_modes(int ch) { +	if (ch == '1') w2_send_mode(W2_M_MAZE); +	if (ch == '2') w2_send_mode(W2_M_GRID); +	if (ch == '3') w2_send_mode(W2_M_HALT); +	if (ch == '4') w2_send_mode(W2_M_CHRG); +	if (ch == '5') w2_send_mode(W2_M_SPIN); +	if (ch == '6') w2_send_mode(W2_M_SCAL); + +	if (ch == '0') w2_send_mode(W2_M_PREV); +} + +void w2_ui_tab_modes(bool first) { w2_wmvaddstr(g_w2_ui_pad_body, 0, 0, W2_UI_MODES_INFO); } diff --git a/client/ui_orders.c b/client/ui_orders.c new file mode 100644 index 0000000..6c5de27 --- /dev/null +++ b/client/ui_orders.c @@ -0,0 +1,112 @@ +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "../shared/bin.h" +#include "../shared/protocol.h" +#include "../shared/util.h" +#include "commands.h" +#include "errcatch.h" +#include "i18n.h" +#include "main.h" +#include "ui.h" + +#define W2_IS_CMD(cmd) strncmp(g_w2_command_buffer, cmd, sizeof(cmd) - 1) == 0 +#define W2_UI_ORDERS_PRINT_CONST(text)                                                             \ +	w2_wmvaddstr(g_w2_ui_pad_body, g_w2_order_line, 0, text);                                      \ +	g_w2_order_line += w2_newline_count(text, sizeof(text)); + +char g_w2_command_buffer[W2_UI_ORDER_CMD_BUFFER_SIZE] = {0x00}; +int g_w2_command_buffer_index						  = 0; +int g_w2_order_line									  = 0; +bool g_w2_order_recording							  = false; +bool g_w2_order_saved								  = false; +uint16_t g_w2_order_buffer[W2_UI_ORDER_BUFFER_SIZE]	  = {0}; +int g_w2_order_buffer_index							  = 0; + +void w2_ui_orders_cmd_error() { W2_UI_ORDERS_PRINT_CONST(W2_UI_ORDER_MSG_ERROR); } + +void w2_ui_orders_cmd_help() { W2_UI_ORDERS_PRINT_CONST(W2_UI_ORDER_MSG_HELP); } + +void w2_ui_orders_cmd_start() { +	if (g_w2_order_recording) { +		W2_UI_ORDERS_PRINT_CONST(W2_UI_ORDER_MSG_ORDER_START_ERR); +	} else { +		W2_UI_ORDERS_PRINT_CONST(W2_UI_ORDER_MSG_ORDER_START_OK); +		g_w2_order_buffer_index = 0; +	} +	g_w2_order_recording = true; +} + +void w2_ui_orders_cmd_coordinate() { +	if (!g_w2_order_recording) { +		W2_UI_ORDERS_PRINT_CONST(W2_UI_ORDER_MSG_ORDER_APPEND_ERR); +		return; +	} +	unsigned int x, y; +	if (sscanf(g_w2_command_buffer, W2_UI_ORDER_CMD_COORDINATE " %u %u", &x, &y) != 2) +		return w2_ui_orders_cmd_error(); +	g_w2_order_buffer[g_w2_order_buffer_index++] = y * g_w2_state.map_width + x; +	W2_UI_ORDERS_PRINT_CONST(W2_UI_ORDER_MSG_ORDER_APPEND_OK); +} + +void w2_ui_orders_cmd_done() { +	if (g_w2_order_recording) { +		W2_UI_ORDERS_PRINT_CONST(W2_UI_ORDER_MSG_ORDER_DONE_OK); +	} else { +		W2_UI_ORDERS_PRINT_CONST(W2_UI_ORDER_MSG_ORDER_DONE_ERR); +	} +	g_w2_order_saved	 = true; +	g_w2_order_recording = false; +} + +void w2_ui_orders_cmd_send() { +	for (int i = 0; i < g_w2_order_buffer_index; i++) { +		W2_CREATE_MSG_BIN(w2_s_cmd_bomd_rx, msg, bin); + +		msg->position = w2_bin_hton16(g_w2_order_buffer[i]); +		msg->id		  = rand(); + +		w2_send_bin(bin); +		free(bin); +	} +	W2_UI_ORDERS_PRINT_CONST(W2_UI_ORDER_MSG_ORDER_SENT); +} + +void w2_ui_orders_process_cmd() { +	if (g_w2_command_buffer_index == 0) return w2_ui_orders_cmd_error(); +	if (W2_IS_CMD(W2_UI_ORDER_CMD_HELP)) return w2_ui_orders_cmd_help(); +	if (W2_IS_CMD(W2_UI_ORDER_CMD_START)) return w2_ui_orders_cmd_start(); +	if (W2_IS_CMD(W2_UI_ORDER_CMD_COORDINATE)) return w2_ui_orders_cmd_coordinate(); +	if (W2_IS_CMD(W2_UI_ORDER_CMD_DONE)) return w2_ui_orders_cmd_done(); +	if (W2_IS_CMD(W2_UI_ORDER_CMD_SEND)) return w2_ui_orders_cmd_send(); +	return w2_ui_orders_cmd_error(); +} + +void w2_ui_onkey_orders(int ch) { +	if (ch >= 'A' && ch <= 'Z') ch += 0x20; // convert uppercase to lowercase +	if ((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == ' ')) { +		g_w2_command_buffer[g_w2_command_buffer_index] = ch; +		g_w2_command_buffer_index = +			W2_MIN(g_w2_command_buffer_index + 1, W2_UI_ORDER_CMD_BUFFER_SIZE - 1); +	} else if (ch == KEY_BACKSPACE) { +		g_w2_command_buffer_index					   = W2_MAX(g_w2_command_buffer_index - 1, 0); +		g_w2_command_buffer[g_w2_command_buffer_index] = 0x00; +	} else if (ch == 0x0a) { +		// clear cursor +		wmove(g_w2_ui_pad_body, g_w2_order_line, g_w2_command_buffer_index + 2); +		waddstr(g_w2_ui_pad_body, " "); + +		g_w2_order_line += 1; +		w2_ui_orders_process_cmd(); +		memset(g_w2_command_buffer, 0x00, W2_UI_ORDER_CMD_BUFFER_SIZE); +		g_w2_command_buffer_index = 0; +	} +} + +void w2_ui_tab_orders(bool first) { +	if (first) g_w2_order_line = 0; +	char temp[100]; +	sprintf(temp, "> %s_ ", g_w2_command_buffer); +	w2_wmvaddstr(g_w2_ui_pad_body, g_w2_order_line, 0, temp); +} diff --git a/client/ui_start.c b/client/ui_start.c new file mode 100644 index 0000000..118bc01 --- /dev/null +++ b/client/ui_start.c @@ -0,0 +1,8 @@ +#include "i18n.h" +#include "ui.h" + +void w2_ui_tab_start(bool first) { +	g_w2_ui_pad_body_scroll = 0; +	refresh(); +	w2_wmvaddstr(g_w2_ui_pad_body, 0, 0, W2_UI_TAB_START_MESSAGE); +} diff --git a/client/ui_tabbar.c b/client/ui_tabbar.c new file mode 100644 index 0000000..637d2f3 --- /dev/null +++ b/client/ui_tabbar.c @@ -0,0 +1,33 @@ +#include <stdlib.h> +#include <string.h> + +#include "strings.h" +#include "ui.h" + +unsigned int g_w2_ui_tabbar_scroll = 0; +unsigned int g_w2_ui_tabbar_lengths[W2_UI_TAB_COUNT]; +void (*g_w2_tab_ptrs[W2_UI_TAB_COUNT])(bool first); +void (*g_w2_keyhndl_ptrs[W2_UI_TAB_COUNT])(int key); + +void w2_ui_tabbar_init() { +	g_w2_tab_ptrs[W2_UI_TAB_START]		= &w2_ui_tab_start; +	g_w2_tab_ptrs[W2_UI_TAB_ERRCATCH]	= &w2_ui_tab_errcatch; +	g_w2_keyhndl_ptrs[W2_UI_TAB_START]	= &w2_ui_onkey_errcatch; +	g_w2_tab_ptrs[W2_UI_TAB_DIRC]		= &w2_ui_tab_dirc; +	g_w2_keyhndl_ptrs[W2_UI_TAB_DIRC]	= &w2_ui_onkey_dirc; +	g_w2_tab_ptrs[W2_UI_TAB_ORDERS]		= &w2_ui_tab_orders; +	g_w2_keyhndl_ptrs[W2_UI_TAB_ORDERS] = &w2_ui_onkey_orders; +	g_w2_tab_ptrs[W2_UI_TAB_MODES]		= &w2_ui_tab_modes; +	g_w2_keyhndl_ptrs[W2_UI_TAB_MODES]	= &w2_ui_onkey_modes; +} + +void w2_ui_paint_tabbar() { +	wmove(g_w2_ui_pad_tabbar, 0, 0); +	for (unsigned int i = 0; i < W2_UI_TAB_COUNT; i++) { +		g_w2_ui_tabbar_lengths[i] += 2 + strlen(g_w2_tab_strings[i]); + +		wprintw(g_w2_ui_pad_tabbar, " %c%s%c", g_w2_ui_current_tab == i ? '[' : ' ', +				g_w2_tab_strings[i], g_w2_ui_current_tab == i ? ']' : ' '); +	} +	wprintw(g_w2_ui_pad_tabbar, " "); +} diff --git a/protocol.md b/protocol.md index 9c45f56..b627913 100644 --- a/protocol.md +++ b/protocol.md @@ -103,11 +103,10 @@ execution mode. **mode** can be one of:  - 0: mode_maze  - 1: mode_grid  - 2: mode_halt -- 3: mode_lcal -- 4: mode_chrg -- 5: mode_dirc -- 6: mode_spin -- 7: mode_scal +- 3: mode_chrg +- 4: mode_dirc +- 5: mode_spin +- 6: mode_scal  #### get mode (`r --> c`) (2 bytes) @@ -15,10 +15,14 @@ are only supported on linux:  |-|:-:|:-:|  |robot code compilation (avr)|yes|yes|  |robot exec upload|yes|yes| -|client code compilation|yes|yes| +|client code compilation| |yes|  |robot code simulation (x86)| |yes|  |use client with robot sim| |yes| +the client only compiles and runs on linux due to time constraints. because +package names vary from distribution to distribution, no scripts are included +to install the necessary build tools for linux. +  ## toolchain installation on windows  > look in the scripts/ subdirectory if you're concerned about what these diff --git a/robot/errcatch.c b/robot/errcatch.c index 17c96fa..3830d54 100644 --- a/robot/errcatch.c +++ b/robot/errcatch.c @@ -16,6 +16,12 @@ void w2_errcatch_handle_error(w2_s_error *error) {  		case W2_E_WARN_UNCAUGHT_ERROR: {  			break;  		} +		case W2_E_WARN_OBSTACLE_DETECTED: +			break; +		case W2_E_CRIT_OBSTACLE_STUCK: +			break; +		case W2_E_WARN_MODE_HISTORY_BUFFER_IOB: +			break;  		default: {  			g_w2_error_uncaught = true;  #ifdef W2_SIM diff --git a/robot/hypervisor.c b/robot/hypervisor.c index 2a6120b..be3fb77 100644 --- a/robot/hypervisor.c +++ b/robot/hypervisor.c @@ -14,6 +14,9 @@ unsigned long g_w2_hypervisor_ema_io_ms					   = 0;  unsigned long g_w2_hypervisor_ema_mode_ms				   = 0;  uint64_t g_w2_hypervisor_timers[W2_HYPERVISOR_TIMER_COUNT] = {0}; +uint64_t g_w2_hypervisor_ms_timer_offset	= 0; +uint64_t g_w2_hypervisor_ms_timer_cpu_ticks = 0; +  unsigned int g_w2_ping_ms = 0;  uint8_t g_w2_ping_id	  = 0;  bool g_w2_ping_received	  = true; @@ -26,17 +29,17 @@ void w2_hypervisor_main() {  	if (DBG_ENABLE_CYCLEINFO) siminfo("cycle start\n");  #endif -	g_w2_hypervisor_uptime_ms += get_ms(); -	time_reset(); +	g_w2_hypervisor_uptime_ms += w2_get_ms(); +	w2_time_reset();  	w2_sercomm_main(); -	unsigned long sercomm_time = get_ms(); +	unsigned long sercomm_time = w2_get_ms();  	w2_errcatch_main(); -	unsigned long errcatch_time = get_ms() - sercomm_time; -	// w2_io_main(); -	unsigned long io_time = get_ms() - errcatch_time; +	unsigned long errcatch_time = w2_get_ms() - sercomm_time; +	w2_io_main(); +	unsigned long io_time = w2_get_ms() - errcatch_time;  	w2_modes_main(); -	unsigned long mode_time = get_ms() - io_time; +	unsigned long mode_time = w2_get_ms() - io_time;  	// calculate exponential moving averages  	g_w2_hypervisor_ema_sercomm_ms = @@ -58,6 +61,12 @@ void w2_hypervisor_main() {  	g_w2_hypervisor_cycles++;  } +uint64_t w2_get_ms() { +	return ticks_to_microseconds(get_ticks() - g_w2_hypervisor_ms_timer_offset) / 1e3; +} + +void w2_time_reset() { g_w2_hypervisor_ms_timer_offset = get_ticks(); } +  void w2_hypervisor_time_start(uint8_t label) {  	g_w2_hypervisor_timers[label] = g_w2_hypervisor_uptime_ms;  } diff --git a/robot/hypervisor.h b/robot/hypervisor.h index 4b1ed9b..e9699cf 100644 --- a/robot/hypervisor.h +++ b/robot/hypervisor.h @@ -7,9 +7,10 @@  #include "../shared/bool.h"  /** amount of parallel timers */ -#define W2_HYPERVISOR_TIMER_COUNT (1) +#define W2_HYPERVISOR_TIMER_COUNT 2 -#define W2_TIMER_PING (0) +#define W2_TIMER_PING 0 +#define W2_TIMER_OBJECT_DETECTION 1  extern uint64_t g_w2_hypervisor_cycles;  extern uint64_t g_w2_hypervisor_uptime_ms; @@ -32,6 +33,15 @@ extern bool g_w2_connected;   */  void w2_hypervisor_main(); +/** + * pololu's `get_ms()` estimates run time by only adding the CPU time taken up + * by pololu library functions. this function uses the `get_ticks()` function + * to calculate elapsed milliseconds, and should therefore be more accurate. + */ +uint64_t w2_get_ms(); +/** reset time returned by `w2_get_ms()` */ +void w2_time_reset(); +  /** start timer with label `label` */  void w2_hypervisor_time_start(uint8_t label);  /** stop timer with label `label` */ @@ -1,35 +1,36 @@ -#include <string.h> - -#include "../shared/consts.h"  #include "io.h" +#include "../shared/consts.h" +#include "../shared/errcatch.h" +#include "hypervisor.h"  #include "modes.h"  #include "orangutan_shim.h" -w2_s_io_all g_w2_io; +#include <stdio.h> + +bool g_w2_io_object_detected = false; + +void w2_io_object_detection() { +	unsigned int front_distance = analog_read(W2_FRONT_SENSOR_PIN); + +	if (g_w2_mode_history[g_w2_mode_history_index] == W2_M_HALT) return; + +	if (!g_w2_io_object_detected && front_distance >= W2_IO_DISTANCE_CLOSE_THRESHOLD) { +		g_w2_io_object_detected = true; +		w2_hypervisor_time_start(W2_TIMER_OBJECT_DETECTION); +		w2_errcatch_throw(W2_E_WARN_OBSTACLE_DETECTED); +	} + +	if (g_w2_io_object_detected) { +		if (front_distance <= W2_IO_DISTANCE_FAR_THRESHOLD) g_w2_io_object_detected = false; +		if (w2_hypervisor_time_end(W2_TIMER_OBJECT_DETECTION) >= W2_IO_DISTANCE_TOO_CLOSE_TIMEOUT) +			w2_errcatch_throw(W2_E_CRIT_OBSTACLE_STUCK); +		set_motors(0, 0); +	} +}  void w2_io_main() { -	g_w2_io.button[0].pressed = get_single_debounced_button_press(BUTTON_A); -	g_w2_io.button[1].pressed = get_single_debounced_button_press(BUTTON_B); -	g_w2_io.button[2].pressed = get_single_debounced_button_press(BUTTON_C); -	g_w2_io.button[3].pressed = get_single_debounced_button_press(TOP_BUTTON); -	g_w2_io.button[4].pressed = get_single_debounced_button_press(BOTTOM_BUTTON); - -	unsigned int sensor_values[5]; -	qtr_read(sensor_values, QTR_EMITTERS_ON); -	for (int i = 0; i < 5; i++) g_w2_io.qtr[i].range = sensor_values[i]; - -	// TODO average voltage over mutiple samples sensor -	g_w2_io.battery.charge_level	 = analog_read(W2_BATTERY_PIN); -	g_w2_io.front_distance.detection = analog_read(W2_FRONT_SENSOR_PIN); -	g_w2_io.side_distance.detection	 = analog_read(W2_SIDE_SENSOR_PIN); - -	set_motors(g_w2_io.motor_left.speed, g_w2_io.motor_right.speed); -	red_led(g_w2_io.led_red.on); -	green_led(g_w2_io.led_green.on); - -	// TODO don't do this every cycle -	char text_copy[17]; -	memcpy((char *)text_copy, g_w2_io.lcd.text, 16); -	text_copy[16] = 0x00; -	print(text_copy); -}; +	w2_io_object_detection(); +	// TODO: battery status + +	return; +} @@ -1,11 +1,10 @@  #pragma once +#include "../shared/bool.h" +  /** @file io.h */ -#include "../shared/io.h" +extern bool g_w2_io_object_detected;  /** @brief i/o module main */  void w2_io_main(); - -/** @brief global struct containing all i/o */ -extern w2_s_io_all g_w2_io; diff --git a/robot/mode_dirc.c b/robot/mode_dirc.c index 7021721..d9c0d17 100644 --- a/robot/mode_dirc.c +++ b/robot/mode_dirc.c @@ -10,16 +10,5 @@  int16_t g_w2_mode_dirc_motor_l = 0;  int16_t g_w2_mode_dirc_motor_r = 0; -uint8_t g_w2_mode_dirc_power   = 100; -void w2_mode_dirc() { -	if (g_w2_connected == 1) -		g_w2_mode_dirc_power = 100; -	else -		g_w2_mode_dirc_power = W2_MAX(0, g_w2_mode_dirc_power - 1); - -	if (g_w2_mode_dirc_power == 0) w2_modes_call(W2_M_HALT); - -	set_motors(g_w2_mode_dirc_motor_l * g_w2_mode_dirc_power / 100, -			   g_w2_mode_dirc_motor_r * g_w2_mode_dirc_power / 100); -} +void w2_mode_dirc() { set_motors(g_w2_mode_dirc_motor_l, g_w2_mode_dirc_motor_r); } diff --git a/robot/mode_halt.c b/robot/mode_halt.c index 88d6183..083d45b 100644 --- a/robot/mode_halt.c +++ b/robot/mode_halt.c @@ -1,3 +1,4 @@  #include "mode_halt.h" +#include "orangutan_shim.h" -void w2_mode_halt() { return; } +void w2_mode_halt() { set_motors(0, 0); } diff --git a/robot/mode_lcal.c b/robot/mode_lcal.c deleted file mode 100644 index 896d0f0..0000000 --- a/robot/mode_lcal.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "mode_lcal.h" - -void w2_mode_lcal() {} diff --git a/robot/mode_lcal.h b/robot/mode_lcal.h deleted file mode 100644 index 5a43701..0000000 --- a/robot/mode_lcal.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -/** @file mode_lcal.h */ - -/** - * calibration mode - * - * turns robot on its own axis 360 degress, and aligns the front sensors with - * the line if found, else triggers halt mode (emergency) - */ -void w2_mode_lcal(); diff --git a/robot/mode_scal.c b/robot/mode_scal.c index f3178d7..53cbf67 100644 --- a/robot/mode_scal.c +++ b/robot/mode_scal.c @@ -1,19 +1,20 @@  #include "mode_scal.h" +#include "modes.h" +#include "orangutan_shim.h"  void w2_mode_scal() { -	// TODO ??? -	/* pololu_3pi_init(2000); +	pololu_3pi_init(2000);  	for (int counter = 0; counter < 80; counter++) {  		if (counter < 20 || counter >= 60) { -			g_w2_io.motor_left.speed  = 40; -			g_w2_io.motor_right.speed = -40; +			set_motors(40, -40);  		} else { -			g_w2_io.motor_left.speed  = -40; -			g_w2_io.motor_right.speed = 40; +			set_motors(-40, 40);  		}  		calibrate_line_sensors(IR_EMITTERS_ON); -		delay_ms(20); // TODO foei -	} */ +		delay_ms(20); +	} + +	w2_modes_call(W2_M_PREV);  } diff --git a/robot/mode_spin.c b/robot/mode_spin.c index 9145eb3..9ee83b0 100644 --- a/robot/mode_spin.c +++ b/robot/mode_spin.c @@ -1,3 +1,4 @@  #include "mode_spin.h" +#include "orangutan_shim.h" -void w2_mode_spin() {} +void w2_mode_spin() { set_motors(255, -255); } diff --git a/robot/modes.c b/robot/modes.c index 7decf47..4995d6f 100644 --- a/robot/modes.c +++ b/robot/modes.c @@ -8,7 +8,6 @@  #include "mode_dirc.h"  #include "mode_grid.h"  #include "mode_halt.h" -#include "mode_lcal.h"  #include "mode_maze.h"  #include "mode_scal.h"  #include "mode_spin.h" @@ -22,7 +21,6 @@ void w2_modes_init() {  	g_w2_modes[W2_M_DIRC] = &w2_mode_dirc;  	g_w2_modes[W2_M_GRID] = &w2_mode_grid;  	g_w2_modes[W2_M_HALT] = &w2_mode_halt; -	g_w2_modes[W2_M_LCAL] = &w2_mode_lcal;  	g_w2_modes[W2_M_MAZE] = &w2_mode_maze;  	g_w2_modes[W2_M_SCAL] = &w2_mode_scal;  	g_w2_modes[W2_M_SPIN] = &w2_mode_spin; @@ -48,7 +46,7 @@ void w2_modes_switch(w2_e_mode new_mode, bool replace) {  	// forward mode change to sercomm  	W2_CREATE_MSG_BIN(w2_s_cmd_mode_tx, msg, msg_bin);  	msg->opcode = W2_CMD_MODE | W2_CMDDIR_TX; -	msg->mode	= new_mode; +	msg->mode	= g_w2_mode_history[g_w2_mode_history_index];  	w2_sercomm_append_msg(msg_bin);  	free(msg_bin); diff --git a/robot/readme.md b/robot/readme.md index f54af21..e8316e3 100644 --- a/robot/readme.md +++ b/robot/readme.md @@ -50,8 +50,7 @@ organizational and form more of a software 'skeleton', while the 'maze' and                                                            Maze ─┤                                                       Warehouse ─┤                                                  Emergency stop ─┤ -                        *logic modes* ->          Line finding ─┤ -                                                Charge station ─┤ +                          *logic modes* ->      Charge station ─┤                                                  Direct control ─┤                                                       Wet floor ─┤                                              Sensor calibration ─┘ @@ -74,11 +73,10 @@ what they're supposed to do:  |maze              |`mode_maze  `|done|Jorn & Abdullaahi| controls robot during maze portion of map; hands off control to warehouse module|  |warehouse         |`mode_grid  `|may 31|Loek| controls robot during warehouse portion of map; hands off control to maze module|  |emergency stop    |`mode_halt  `|done|Fiona| stops all execution until emergency mode is reset by software or user| -|line finding      |`mode_lcal  `|may 31|Fiona| find line by turning on own axis if lost|  |charge station    |`mode_chrg  `|may 31|Fiona| go to the charging station transition in the grid, and continue until a black circle is found|  |direct control    |`mode_dirc  `|done|Loek| respond to [DIRC](../protocol.md#DIRC) commands| -|wet floor         |`mode_spin  `|may 31|Fiona| spin uncontrollably (simulating wet floor??)| -|sensor calibration|`mode_scal  `|may 31|Jorn & Abdullaahi| calibrate underside uv sensors| +|wet floor         |`mode_spin  `|done|Fiona| spin uncontrollably (simulating wet floor??)| +|sensor calibration|`mode_scal  `|done|Jorn & Abdullaahi| calibrate underside uv sensors|  ## some standards diff --git a/robot/sercomm.c b/robot/sercomm.c index c50dd15..efad449 100644 --- a/robot/sercomm.c +++ b/robot/sercomm.c @@ -99,7 +99,11 @@ void w2_cmd_ping_rx(w2_s_bin *data) { w2_sercomm_append_msg(data); }  void w2_cmd_mode_rx(w2_s_bin *data) {  	W2_CAST_BIN(w2_s_cmd_mode_rx, data, req); -	w2_modes_swap(req->mode); +	if (req->mode == W2_M_SCAL) { +		w2_modes_call(req->mode); +	} else { +		w2_modes_swap(req->mode); +	}  }  void w2_cmd_sped_rx(w2_s_bin *data) { return; } @@ -135,22 +139,6 @@ void w2_cmd_sres_rx(w2_s_bin *data) {  void w2_cmd_mcfg_rx(w2_s_bin *data) { return; } -void w2_cmd_sens_rx(w2_s_bin *data) { -	W2_CREATE_MSG_BIN(w2_s_cmd_sens_tx, res_msg, res_bin); -	res_msg->opcode = W2_CMD_SENS | W2_CMDDIR_TX; -	memcpy((uint8_t *)&res_msg->io, (uint8_t *)&g_w2_io, sizeof(w2_s_io_all)); - -	for (int i = 0; i < 5; i++) w2_bin_repl_hton16(&res_msg->io.qtr[i].range); -	w2_bin_repl_hton16(&res_msg->io.front_distance.detection); -	w2_bin_repl_hton16(&res_msg->io.side_distance.detection); -	w2_bin_repl_hton16(&res_msg->io.battery.charge_level); -	w2_bin_repl_hton16((uint16_t *)&res_msg->io.motor_left.speed); -	w2_bin_repl_hton16((uint16_t *)&res_msg->io.motor_right.speed); - -	w2_sercomm_append_msg(res_bin); -	free(res_bin); -} -  void w2_cmd_info_rx(w2_s_bin *data) {  	W2_CREATE_MSG_BIN(w2_s_cmd_info_tx, res_msg, res_bin);  	res_msg->opcode = W2_CMD_INFO | W2_CMDDIR_TX; diff --git a/robot/setup.c b/robot/setup.c index 4706d64..dfd88bd 100644 --- a/robot/setup.c +++ b/robot/setup.c @@ -34,6 +34,9 @@ void w2_setup_main() {  	w2_modes_swap(W2_M_MAZE);  	w2_modes_call(W2_M_HALT); +	// send info +	w2_cmd_info_rx(NULL); +  	// indicate startup done  	play("L50 c>c");  } diff --git a/shared/consts.h b/shared/consts.h index cd6dff1..9c2358f 100644 --- a/shared/consts.h +++ b/shared/consts.h @@ -4,7 +4,7 @@  #ifndef W2_BUILD_STR  // is defined by CFLAGS += -DW2_BUILD_STR in makefile -#define W2_BUILD_STR ("????????") +#define W2_BUILD_STR "????????"  #endif  #if !defined W2_HOST_WIN32 && !defined W2_HOST_LINUX @@ -13,27 +13,38 @@  #endif  /** serial baud rate (bit/s) */ -#define W2_SERIAL_BAUD (9600) +#define W2_SERIAL_BAUD 9600  /** size of input (receive) buffer (in bytes) */ -#define W2_SERIAL_READ_BUFFER_SIZE (255) +#define W2_SERIAL_READ_BUFFER_SIZE 255  /** size of the error handling buffer (in errors, not bytes) */ -#define W2_ERROR_BUFFER_SIZE (16) +#define W2_ERROR_BUFFER_SIZE 16  /** size of the serial communication buffer (in messages, not bytes) */ -#define W2_SERCOMM_BUFFER_SIZE (16) +#define W2_SERCOMM_BUFFER_SIZE 16  /** size of mode history buffer */ -#define W2_MODE_HISTORY_BUFFER_SIZE (8) +#define W2_MODE_HISTORY_BUFFER_SIZE 8  /** max logic module execution time in milliseconds */ -#define W2_MAX_MODULE_CYCLE_MS (20) +#define W2_MAX_MODULE_CYCLE_MS 20  /** exponential moving average new measurement weight (double 0-1) */ -#define W2_EMA_WEIGHT (0.10) +#define W2_EMA_WEIGHT 0.10  /** minimal time between pings */ -#define W2_PING_FREQUENCY (1e3) +#define W2_PING_FREQUENCY 1e3  /** max time between ping and answer */ -#define W2_PING_TIMEOUT (5e3) +#define W2_PING_TIMEOUT 5e3 + +/** default map width/height */ +#define W2_MAP_DEFAULT_HEIGHT 5 +#define W2_MAP_DEFAULT_WIDTH 5 + +/** distance too close schmitt trigger low threshold */ +#define W2_IO_DISTANCE_CLOSE_THRESHOLD 400 +/** distance too close schmitt trigger high threshold */ +#define W2_IO_DISTANCE_FAR_THRESHOLD 100 +/** go into emergency mode if object still present after n ms */ +#define W2_IO_DISTANCE_TOO_CLOSE_TIMEOUT 5e3  /** front-facing distance sensor pinout */  #define W2_FRONT_SENSOR_PIN 5 diff --git a/shared/io.h b/shared/io.h deleted file mode 100644 index 584ad1e..0000000 --- a/shared/io.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include <stdio.h> - -#include "bool.h" - -#pragma pack(push, 1) - -/** momentary button input struct */ -typedef struct { -	bool pressed; -} w2_s_i_push; - -/** qtr contrast sensor input struct */ -typedef struct { -	uint16_t range; -} w2_s_i_contrast; - -/** distance sensor input struct */ -typedef struct { -	uint16_t detection; -} w2_s_i_distance; - -/** battery input struct */ -typedef struct { -	uint16_t charge_level; -} w2_s_i_battery; - -/** motor output struct */ -typedef struct { -	int16_t speed; -} w2_s_o_motor; - -/** underside led output struct */ -typedef struct { -	bool on; -} w2_s_o_led; - -/** lcd output struct */ -typedef struct { -	char text[16]; -} w2_s_o_display; - -/** struct containing all i/o */ -typedef struct { -	w2_s_i_push button[5]; -	w2_s_i_contrast qtr[5]; -	w2_s_i_distance front_distance; -	w2_s_i_distance side_distance; -	w2_s_i_battery battery; - -	w2_s_o_motor motor_left; -	w2_s_o_motor motor_right; -	w2_s_o_led led_red; -	w2_s_o_led led_green; -	w2_s_o_display lcd; -} w2_s_io_all; - -#pragma pack(pop) diff --git a/shared/modes.h b/shared/modes.h index ff939ea..b58a760 100644 --- a/shared/modes.h +++ b/shared/modes.h @@ -1,6 +1,6 @@  #pragma once -#define W2_MODE_COUNT 8 +#define W2_MODE_COUNT 7  /** mode constants */  typedef enum { @@ -8,9 +8,8 @@ typedef enum {  	W2_M_MAZE = 0,  	W2_M_GRID = 1,  	W2_M_HALT = 2, -	W2_M_LCAL = 3, -	W2_M_CHRG = 4, -	W2_M_DIRC = 5, -	W2_M_SPIN = 6, -	W2_M_SCAL = 7, +	W2_M_CHRG = 3, +	W2_M_DIRC = 4, +	W2_M_SPIN = 5, +	W2_M_SCAL = 6,  } w2_e_mode; diff --git a/shared/protocol.c b/shared/protocol.c index 9be1d31..02d746a 100644 --- a/shared/protocol.c +++ b/shared/protocol.c @@ -18,8 +18,6 @@ void w2_cmd_setup_handlers() {  	g_w2_cmd_handlers[W2_CMD_BOMD | W2_CMDDIR_TX] = w2_cmd_bomd_tx;  	g_w2_cmd_handlers[W2_CMD_SRES | W2_CMDDIR_RX] = w2_cmd_sres_rx;  	g_w2_cmd_handlers[W2_CMD_MCFG | W2_CMDDIR_RX] = w2_cmd_mcfg_rx; -	g_w2_cmd_handlers[W2_CMD_SENS | W2_CMDDIR_RX] = w2_cmd_sens_rx; -	g_w2_cmd_handlers[W2_CMD_SENS | W2_CMDDIR_TX] = w2_cmd_sens_tx;  	g_w2_cmd_handlers[W2_CMD_INFO | W2_CMDDIR_RX] = w2_cmd_info_rx;  	g_w2_cmd_handlers[W2_CMD_INFO | W2_CMDDIR_TX] = w2_cmd_info_tx;  	g_w2_cmd_handlers[W2_CMD_DISP | W2_CMDDIR_RX] = w2_cmd_disp_rx; @@ -46,9 +44,6 @@ size_t w2_cmd_sizeof(uint8_t data[W2_SERIAL_READ_BUFFER_SIZE], uint8_t data_leng  	if (data[0] == (W2_CMD_SRES | W2_CMDDIR_RX)) return sizeof(w2_s_cmd_sres_rx); -	if (data[0] == (W2_CMD_SENS | W2_CMDDIR_RX)) return sizeof(w2_s_cmd_sens_rx); -	if (data[0] == (W2_CMD_SENS | W2_CMDDIR_TX)) return sizeof(w2_s_cmd_sens_tx); -  	if (data[0] == (W2_CMD_INFO | W2_CMDDIR_RX)) return sizeof(w2_s_cmd_info_rx);  	if (data[0] == (W2_CMD_INFO | W2_CMDDIR_TX)) return sizeof(w2_s_cmd_info_tx); diff --git a/shared/protocol.h b/shared/protocol.h index 02d5526..5e1a12b 100644 --- a/shared/protocol.h +++ b/shared/protocol.h @@ -8,7 +8,6 @@  #include "bin.h"  #include "bool.h"  #include "consts.h" -#include "io.h"  #define W2_SERIAL_START_BYTE 0xff @@ -136,15 +135,6 @@ typedef struct {  typedef struct {  	uint8_t opcode; -} w2_s_cmd_sens_rx; - -typedef struct { -	uint8_t opcode; -	w2_s_io_all io; -} w2_s_cmd_sens_tx; - -typedef struct { -	uint8_t opcode;  } w2_s_cmd_info_rx;  typedef struct { @@ -205,10 +195,6 @@ void w2_cmd_bomd_tx(w2_s_bin *data);  void w2_cmd_sres_rx(w2_s_bin *data);  /** handler for mcfg_rx (on complete message) */  void w2_cmd_mcfg_rx(w2_s_bin *data); -/** handler for sens_rx (on complete message) */ -void w2_cmd_sens_rx(w2_s_bin *data); -/** handler for sens_tx (on complete message) */ -void w2_cmd_sens_tx(w2_s_bin *data);  /** handler for info_rx (on complete message) */  void w2_cmd_info_rx(w2_s_bin *data);  /** handler for info_tx (on complete message) */ diff --git a/shared/util.c b/shared/util.c index 68503e8..6c5bb1a 100644 --- a/shared/util.c +++ b/shared/util.c @@ -6,3 +6,10 @@ unsigned long w2_util_exp_mov_avg(unsigned long current_avg, unsigned long new_m  }  int w2_sign(int n) { return (n > 0) - (n < 0); } + +unsigned int w2_newline_count(char *str, unsigned int len) { +	unsigned int newlines = 0; +	for (unsigned int i = 0; i < len; i++) +		if (str[i] == '\n') newlines++; +	return newlines; +} diff --git a/shared/util.h b/shared/util.h index 230c3e4..806af3a 100644 --- a/shared/util.h +++ b/shared/util.h @@ -6,5 +6,9 @@  #define W2_MAX(a, b) (((a) > (b)) ? (a) : (b))  #define W2_RANGE(min, val, max) W2_MIN(max, W2_MAX(val, min)) +/** calculate exponential moving average */  unsigned long w2_util_exp_mov_avg(unsigned long current_avg, unsigned long new_meas); +/** return the sign of a number (-1 or 1) */  int w2_sign(int n); +/** return amount of newline characters */ +unsigned int w2_newline_count(char *str, unsigned int len); |