aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/commands.c21
-rw-r--r--client/errcatch.c27
-rw-r--r--client/errcatch.h8
-rw-r--r--client/i18n/en_us.h96
-rw-r--r--client/main.c6
-rw-r--r--client/main.h4
-rw-r--r--client/serial.c9
-rw-r--r--client/serial_win32.c16
-rw-r--r--client/setup.c11
-rw-r--r--client/strings.c81
-rw-r--r--client/strings.h7
-rw-r--r--client/time_windows.c4
-rw-r--r--client/ui.c85
-rw-r--r--client/ui.h43
-rw-r--r--client/ui_dirc.c68
-rw-r--r--client/ui_errcatch.c49
-rw-r--r--client/ui_modes.c16
-rw-r--r--client/ui_orders.c112
-rw-r--r--client/ui_start.c8
-rw-r--r--client/ui_tabbar.c33
-rw-r--r--protocol.md9
-rw-r--r--readme.md6
-rw-r--r--robot/errcatch.c6
-rw-r--r--robot/hypervisor.c23
-rw-r--r--robot/hypervisor.h14
-rw-r--r--robot/io.c59
-rw-r--r--robot/io.h7
-rw-r--r--robot/mode_dirc.c13
-rw-r--r--robot/mode_halt.c3
-rw-r--r--robot/mode_lcal.c3
-rw-r--r--robot/mode_lcal.h11
-rw-r--r--robot/mode_scal.c17
-rw-r--r--robot/mode_spin.c3
-rw-r--r--robot/modes.c4
-rw-r--r--robot/readme.md8
-rw-r--r--robot/sercomm.c22
-rw-r--r--robot/setup.c3
-rw-r--r--shared/consts.h31
-rw-r--r--shared/io.h59
-rw-r--r--shared/modes.h11
-rw-r--r--shared/protocol.c5
-rw-r--r--shared/protocol.h14
-rw-r--r--shared/util.c7
-rw-r--r--shared/util.h4
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)
diff --git a/readme.md b/readme.md
index 610f99d..6072c0d 100644
--- a/readme.md
+++ b/readme.md
@@ -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` */
diff --git a/robot/io.c b/robot/io.c
index 8b34aba..717778a 100644
--- a/robot/io.c
+++ b/robot/io.c
@@ -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;
+}
diff --git a/robot/io.h b/robot/io.h
index 64ce293..31fe410 100644
--- a/robot/io.h
+++ b/robot/io.h
@@ -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);