summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2022-06-07 21:27:16 +0200
committerlonkaars <loek@pipeframe.xyz>2022-06-07 21:27:16 +0200
commit3e65c70da770fa31fc8acc6ab9374d908cf1ed17 (patch)
tree14f8d4c708faccc8b3f992a022f940c00ed694f9
parent8c8322a7a0c251d595a0df054324f82d41966e0a (diff)
implement orders
-rw-r--r--client/i18n/en_us.h39
-rw-r--r--client/main.c6
-rw-r--r--client/main.h3
-rw-r--r--client/setup.c3
-rw-r--r--client/strings.c2
-rw-r--r--client/ui.c4
-rw-r--r--client/ui.h14
-rw-r--r--client/ui_errcatch.c8
-rw-r--r--client/ui_modes.c10
-rw-r--r--client/ui_orders.c116
-rw-r--r--client/ui_tabbar.c4
-rw-r--r--readme.md6
-rw-r--r--shared/consts.h4
-rw-r--r--shared/util.c8
-rw-r--r--shared/util.h4
15 files changed, 205 insertions, 26 deletions
diff --git a/client/i18n/en_us.h b/client/i18n/en_us.h
index 47debd7..ceca215 100644
--- a/client/i18n/en_us.h
+++ b/client/i18n/en_us.h
@@ -24,7 +24,7 @@
#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_MODE "set mode"
+#define W2_UI_TAB_LABEL_MODES "set mode"
#define W2_UI_TAB_START_MESSAGE "" \
"welcome to the wall-e2 console application!\n" \
@@ -33,18 +33,9 @@
"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" \
- "<up>/<down>, <j>/<k> select option\n" \
- "<enter>, <i> edit option\n" \
- "<home>, <g> scroll to top\n" \
- "<end>, <G> scroll to bottom\n" \
- "<escape> back\n" \
- "<q> exit\n" \
+ "<tab> switch to next tab\n" \
+ "<ctrl-c> exit\n" \
"\n" \
- "tab shortcuts:\n" \
- "<N> info <o> orders\n" \
- "<S> logs <M> set mode\n" \
- "<d> direct control <m> map\n"
#define W2_UI_ERROR_SEVERITY_CRIT "CRIT"
#define W2_UI_ERROR_SEVERITY_WARN "WARN"
@@ -86,3 +77,27 @@
#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"
+
diff --git a/client/main.c b/client/main.c
index b5af0e8..dcbc16a 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..cd81348 100644
--- a/client/main.h
+++ b/client/main.h
@@ -13,6 +13,9 @@ 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;
diff --git a/client/setup.c b/client/setup.c
index 8b5d07a..43ed135 100644
--- a/client/setup.c
+++ b/client/setup.c
@@ -33,6 +33,7 @@ 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();
@@ -46,7 +47,7 @@ void w2_client_setup(int argc, char **argv) {
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);
+ g_w2_ui_pad_seperator = newpad(1, g_w2_ui_width + 1);
scrollok(g_w2_ui_pad_body, true);
// check endianness
diff --git a/client/strings.c b/client/strings.c
index 0ab260e..8d63fcb 100644
--- a/client/strings.c
+++ b/client/strings.c
@@ -21,6 +21,8 @@ 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() {
diff --git a/client/ui.c b/client/ui.c
index c45259e..13bcfb2 100644
--- a/client/ui.c
+++ b/client/ui.c
@@ -34,6 +34,7 @@ void w2_wmvaddnstr(WINDOW *win, unsigned int y, unsigned int x, char *str, unsig
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() {
@@ -94,7 +95,6 @@ void w2_ui_paint_statusbar() {
void w2_ui_paint_seperator() {
char temp[g_w2_ui_width];
-
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);
+ 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 a003cfc..c169401 100644
--- a/client/ui.h
+++ b/client/ui.h
@@ -3,13 +3,19 @@
#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 3
+#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;
@@ -47,8 +53,12 @@ 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_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_errcatch.c b/client/ui_errcatch.c
index 5c9cf34..c25f787 100644
--- a/client/ui_errcatch.c
+++ b/client/ui_errcatch.c
@@ -5,16 +5,10 @@
#include "i18n.h"
#include "strings.h"
#include "ui.h"
+#include "../shared/util.h"
unsigned int g_w2_errcatch_log_line = 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;
-}
-
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];
diff --git a/client/ui_modes.c b/client/ui_modes.c
new file mode 100644
index 0000000..933f47b
--- /dev/null
+++ b/client/ui_modes.c
@@ -0,0 +1,10 @@
+#include "ui.h"
+
+void w2_ui_onkey_modes(int ch) {
+
+}
+
+void w2_ui_tab_modes(bool first) {
+
+}
+
diff --git a/client/ui_orders.c b/client/ui_orders.c
new file mode 100644
index 0000000..4951ba6
--- /dev/null
+++ b/client/ui_orders.c
@@ -0,0 +1,116 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "ui.h"
+#include "errcatch.h"
+#include "../shared/util.h"
+#include "../shared/bin.h"
+#include "../shared/protocol.h"
+#include "i18n.h"
+#include "commands.h"
+#include "main.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_tabbar.c b/client/ui_tabbar.c
index 87e3f06..1baf559 100644
--- a/client/ui_tabbar.c
+++ b/client/ui_tabbar.c
@@ -15,6 +15,10 @@ void w2_ui_tabbar_init() {
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() {
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/shared/consts.h b/shared/consts.h
index cd6dff1..11e6d14 100644
--- a/shared/consts.h
+++ b/shared/consts.h
@@ -35,6 +35,10 @@
/** max time between ping and answer */
#define W2_PING_TIMEOUT (5e3)
+/** default map width/height */
+#define W2_MAP_DEFAULT_HEIGHT 5
+#define W2_MAP_DEFAULT_WIDTH 5
+
/** front-facing distance sensor pinout */
#define W2_FRONT_SENSOR_PIN 5
/** battery voltage sensor pinout */
diff --git a/shared/util.c b/shared/util.c
index 68503e8..641b4d9 100644
--- a/shared/util.c
+++ b/shared/util.c
@@ -6,3 +6,11 @@ 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);