From 3aaa30cb63ba3203bd2d8c6b977fb61fcaad30a3 Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Tue, 18 Mar 2008 19:30:21 +0100 Subject: [PATCH] refactoring --- control_tab.c | 109 ------- gtdc.c | 15 +- gui_control_tab.c | 53 ++++ graph_tab.c => gui_graph_tab.c | 2 +- variable_tab.c => gui_variable_tab.c | 19 +- gui_variable_tab.h | 13 + tdc_parser.c | 260 ++++++++++++++++ tdc_parser.h | 16 + tdcproto.h => tdc_proto.h | 0 tdc_store.c | 437 +++------------------------ tdc_store.h | 29 +- tdc_variable.c | 179 +++++++++++ tdc_variable.h | 27 ++ variable_tab.h | 13 - 14 files changed, 606 insertions(+), 566 deletions(-) delete mode 100644 control_tab.c create mode 100644 gui_control_tab.c rename graph_tab.c => gui_graph_tab.c (96%) rename variable_tab.c => gui_variable_tab.c (92%) create mode 100644 gui_variable_tab.h create mode 100644 tdc_parser.c create mode 100644 tdc_parser.h rename tdcproto.h => tdc_proto.h (100%) create mode 100644 tdc_variable.c create mode 100644 tdc_variable.h delete mode 100644 variable_tab.h diff --git a/control_tab.c b/control_tab.c deleted file mode 100644 index 260aa4c..0000000 --- a/control_tab.c +++ /dev/null @@ -1,109 +0,0 @@ -#include -#include -#include -#include - -#include "tcpsocket.h" -#include "sockaddr.h" - -#include "tdc_store.h" - -enum { - STAT_DISCONNECTED = 0, - STAT_CONNECTING, - STAT_CONNECTED -}; - -static GtkWidget *button_connect; -static int connect_status = STAT_DISCONNECTED; - -static gint socket_tag; -static int socket_fd; - -static void update_connect_button(void) -{ - if (connect_status == STAT_DISCONNECTED) - gtk_button_set_label(GTK_BUTTON(button_connect), "Connect"); - else - gtk_button_set_label(GTK_BUTTON(button_connect), "Disconnect"); -} - -static void read_cb(gpointer data, gint source, GdkInputCondition condition) -{ - if (tdc_parse_data(source) <= 0) { - g_warning("gtdc:read_cb:read:%s", g_strerror(errno)); - connect_status = STAT_DISCONNECTED; - update_connect_button(); - - gdk_input_remove(socket_tag); - close(source); - } -} - -static void connect_cb(gpointer data, gint source, GdkInputCondition condition) -{ - gdk_input_remove(socket_tag); - - if (tcp_connect_error(source) < 0) { - g_warning("gtdc:connect_cb:tcp_connect_error:%s", g_strerror(errno)); - connect_status = STAT_DISCONNECTED; - close(socket_fd); - - } else { - connect_status = STAT_CONNECTED; - socket_tag = gdk_input_add(socket_fd, GDK_INPUT_READ, read_cb, NULL); - - tdc_flush_vars(); - tdc_send_hello(source); - } - - update_connect_button(); -} - -static void connect_button_cb(GtkWidget *widget, gpointer data) -{ - switch (connect_status) { - case STAT_DISCONNECTED: - connect_status = STAT_CONNECTING; - - struct sockaddr_in sa; - parse_sockaddr("127.0.0.1:5000", &sa); - socket_fd = tcp_connect_nonblock(&sa); - - socket_tag = gdk_input_add(socket_fd, GDK_INPUT_WRITE, connect_cb, NULL); - break; - - case STAT_CONNECTING: - case STAT_CONNECTED: - connect_status = STAT_DISCONNECTED; - - gdk_input_remove(socket_tag); - close(socket_fd); - break; - } - - update_connect_button(); -} - -gint control_tab_init(GtkNotebook *notebook) -{ - GtkWidget *table = gtk_table_new(10, 10, FALSE); - gtk_container_set_border_width(GTK_CONTAINER(table), 10); - - button_connect = gtk_button_new_with_label("Connect"); - gtk_table_attach(GTK_TABLE(table), button_connect, 0, 1, 0, 1, 0, 0, 10, 10); - g_signal_connect(G_OBJECT(button_connect), "clicked", G_CALLBACK(connect_button_cb), NULL); - - /* - * TODO: - * - address field - * - all_variable_refresh_timer - * - graph_variable_refresh_timer - * later: - * - board select - * - connection/protocol details/errors - */ - - GtkWidget *label = gtk_label_new(" Control "); - return gtk_notebook_append_page(GTK_NOTEBOOK(notebook), table, label); -} diff --git a/gtdc.c b/gtdc.c index 031fd66..0628c52 100644 --- a/gtdc.c +++ b/gtdc.c @@ -1,18 +1,15 @@ #include #include -#include "tdc_store.h" -#include "variable_tab.h" +#include "gui_variable_tab.h" -gint control_tab_init(GtkNotebook *notebook); -gint graph_tab_init(GtkNotebook *notebook); +gint gui_ctrltab_init(GtkNotebook *notebook); +gint gui_graphtab_init(GtkNotebook *notebook); int main(int argc, char *argv[]) { gtk_init (&argc, &argv); - tdc_init(); - GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), " gTDC v0.1 "); gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); @@ -25,9 +22,9 @@ int main(int argc, char *argv[]) gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP); gtk_container_add(GTK_CONTAINER(window), notebook); - control_tab_init(GTK_NOTEBOOK(notebook)); - variable_tab_init(GTK_NOTEBOOK(notebook)); - graph_tab_init(GTK_NOTEBOOK(notebook)); + gui_ctrltab_init(GTK_NOTEBOOK(notebook)); + gui_vartab_init(GTK_NOTEBOOK(notebook)); + gui_graphtab_init(GTK_NOTEBOOK(notebook)); gtk_widget_show_all(window); gtk_main(); diff --git a/gui_control_tab.c b/gui_control_tab.c new file mode 100644 index 0000000..8a4af26 --- /dev/null +++ b/gui_control_tab.c @@ -0,0 +1,53 @@ +#include + +#include "tdc_parser.h" + +static GtkWidget *button_connect; +static int connect_status = STAT_DISCONNECTED; + +static void connect_button_update(int status) +{ + connect_status = status; + + if (status == STAT_DISCONNECTED) + gtk_button_set_label(GTK_BUTTON(button_connect), "Connect"); + else + gtk_button_set_label(GTK_BUTTON(button_connect), "Disconnect"); +} + +static void connect_button_cb(GtkWidget *widget, gpointer data) +{ + switch (connect_status) { + case STAT_DISCONNECTED: + tdcparser_connect("127.0.0.1:5000", connect_button_update); + break; + + case STAT_CONNECTING: + case STAT_CONNECTED: + tdcparser_disconnect(); + break; + } +} + +gint gui_ctrltab_init(GtkNotebook *notebook) +{ + GtkWidget *table = gtk_table_new(10, 10, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(table), 10); + + button_connect = gtk_button_new_with_label("Connect"); + gtk_table_attach(GTK_TABLE(table), button_connect, 0, 1, 0, 1, 0, 0, 10, 10); + g_signal_connect(G_OBJECT(button_connect), "clicked", G_CALLBACK(connect_button_cb), NULL); + + /* + * TODO: + * - address field + * - all_variable_refresh_timer + * - graph_variable_refresh_timer + * later: + * - board select + * - connection/protocol details/errors + */ + + GtkWidget *label = gtk_label_new(" Control "); + return gtk_notebook_append_page(GTK_NOTEBOOK(notebook), table, label); +} diff --git a/graph_tab.c b/gui_graph_tab.c similarity index 96% rename from graph_tab.c rename to gui_graph_tab.c index 96e1f51..5a56f14 100644 --- a/graph_tab.c +++ b/gui_graph_tab.c @@ -1,7 +1,7 @@ #include #include -gint graph_tab_init(GtkNotebook *notebook) +gint gui_graphtab_init(GtkNotebook *notebook) { GtkWidget *table = gtk_table_new(3, 3, FALSE); GtkWidget *box = gtk_databox_new(); diff --git a/variable_tab.c b/gui_variable_tab.c similarity index 92% rename from variable_tab.c rename to gui_variable_tab.c index da5d622..7ec65ee 100644 --- a/variable_tab.c +++ b/gui_variable_tab.c @@ -1,7 +1,7 @@ #include #include "tdc_store.h" -#include "tdcproto.h" +#include "tdc_proto.h" enum { COL_ID = 0, /* UINT */ @@ -37,8 +37,6 @@ static void cell_graph_toggle(GtkCellRendererToggle *cell, gtk_list_store_set(GTK_LIST_STORE(user_data), &it, COL_GRAPH, !toggle, -1); - - tdc_store_update_graphlist(); } static gboolean header_toggle_update(GtkTreeModel *model, @@ -112,11 +110,11 @@ static void cell_value_func(GtkTreeViewColumn *column, gtk_tree_model_get(model, iter, COL_VALUE, &var, -1); char buf[32]; - tdc_store_get_varvalue(var, buf, sizeof(buf), viewmode); + tdcvar_get_value(var, buf, sizeof(buf), viewmode); g_object_set(cell, "text", buf, NULL); } -gint variable_tab_init(GtkNotebook *notebook) +gint gui_vartab_init(GtkNotebook *notebook) { list_store = gtk_list_store_new(6, G_TYPE_UINT, G_TYPE_BOOLEAN, @@ -178,13 +176,13 @@ gint variable_tab_init(GtkNotebook *notebook) return gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrollbar, label); } -void vartab_add_var(struct tdc_var *var) +void gui_vartab_add_var(struct tdc_var *var) { GtkTreeIter it; gtk_list_store_append(list_store, &it); char typestr[32]; - tdc_store_get_vartype(var, typestr, sizeof(typestr)); + tdcvar_get_type(var, typestr, sizeof(typestr)); gtk_list_store_set(list_store, &it, COL_ID, var->id, @@ -196,13 +194,14 @@ void vartab_add_var(struct tdc_var *var) -1); } -void vartab_update_var(struct tdc_var *var) +void gui_vartab_update_var(struct tdc_var *var) { - // FIXME: don't update *all* columns when *one* value changed + // FIXME: don't update *all* columns when only *one* value changed gtk_tree_model_foreach(GTK_TREE_MODEL(list_store), header_toggle_update, NULL); } -void vartab_remove_all_vars(void) +void gui_vartab_remove_var(struct tdc_var *var) { + // FIXME: don't remove *all* columns when only *one* should be removed gtk_list_store_clear(list_store); } diff --git a/gui_variable_tab.h b/gui_variable_tab.h new file mode 100644 index 0000000..eb45c74 --- /dev/null +++ b/gui_variable_tab.h @@ -0,0 +1,13 @@ +#ifndef VARIABLE_TAB_H_ +#define VARIABLE_TAB_H_ + +#include +#include "tdc_variable.h" + +gint gui_vartab_init(GtkNotebook *notebook); + +void gui_vartab_add_var(struct tdc_var *var); +void gui_vartab_update_var(struct tdc_var *var); +void gui_vartab_remove_var(struct tdc_var *var); + +#endif /* VARIABLE_TAB_H_ */ diff --git a/tdc_parser.c b/tdc_parser.c new file mode 100644 index 0000000..a7c8cbd --- /dev/null +++ b/tdc_parser.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include + +#include +#include + +#include "sockaddr.h" +#include "tcpsocket.h" + +#include "tdc_parser.h" +#include "tdc_proto.h" +#include "tdc_store.h" +#include "tdc_variable.h" + +static int socket_fd; +static gint socket_tag; +static void (*socket_status_cb)(int status); +static GByteArray *socket_stream; + +static int check_size_helper(int available, + int packet_size, + int expected_base_size, + int packet_data_size, + const char *name) +{ + /* not enough data in buffer */ + if (available < expected_base_size) { + printf("received incomplete %s\n", name); + return 0; + } + + /* retest, after we know that packet_data_size is valid */ + if (available < (expected_base_size + packet_data_size)) { + printf("received incomplete %s\n", name); + return 0; + } + + /* packet has wrong size */ + if (packet_size != (expected_base_size + packet_data_size)) { + printf("received invalid %s\n", name); + return -1; + } + +// printf("received %s\n", name); + return packet_size; +} + +static int tdcparser_send(struct tdc_pkt_header *pkt) +{ + return write(socket_fd, pkt, pkt->size); +} + +void tdcparser_send_hello(void) +{ + int addr; + for (addr = 1; addr < 8; addr++) { + struct tdc_pkt_header pkt; + pkt.cmd = (addr << 4) | TDC_HELLO; + pkt.size = sizeof(pkt); + + tdcparser_send(&pkt); + } +} + +int tdcparser_send_getvars(int address) +{ + struct tdc_pkt_header pkt; + pkt.cmd = (address << 4) | TDC_GETVARS; + pkt.size = sizeof(pkt); + + return tdcparser_send(&pkt); +} + +static int tdcparser_parse(void) +{ + int address = (socket_stream->data[0] & TDC_ADDRMASK) >> 4; + + int remove = 1; + + switch (socket_stream->data[0] & (TDC_REPLY | TDC_OPCODEMASK)) { + case TDC_HELLO: { + struct tdc_pkt_header *pkt = (struct tdc_pkt_header *)socket_stream->data; + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_HELLO"); + /* nothing to do */ + } break; + + case (TDC_HELLO | TDC_REPLY): { + struct tdc_hello_reply *pkt = (struct tdc_hello_reply *)socket_stream->data; + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_HELLO REPLY"); + if (remove <= 0) + break; + + tdcstore_set_name(address, pkt->name); + tdcparser_send_getvars(address); + } break; + + case TDC_GETVARS: { + struct tdc_pkt_header *pkt = (struct tdc_pkt_header *)socket_stream->data; + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVARS"); + /* nothing to do */ + } break; + + case (TDC_GETVARS | TDC_REPLY): { + struct tdc_getvars_reply *pkt = (struct tdc_getvars_reply *)socket_stream->data; + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), + pkt->name_len, "TDC_GETVARS REPLY"); + + if (remove <= 0) + break; + + tdcstore_set_var(address, tdcvar_create(pkt->id, pkt->flags, pkt->name, pkt->name_len)); + } break; + + case TDC_GETVALUE: { + struct tdc_getvalue_request *pkt = (struct tdc_getvalue_request *)socket_stream->data; + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVALUE"); + /* nothing to do */ + } break; + + case (TDC_GETVALUE | TDC_REPLY): { + struct tdc_getvalue_reply *pkt = (struct tdc_getvalue_reply *)socket_stream->data; + + /* check base packet */ + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVALUE REPLY"); + if (remove <= 0) + break; + + struct tdc_var *var = tdcstore_get_var(address, pkt->id); + if (var == NULL) { + printf("unknown variable %d\n", pkt->id); + break; + } + + int varsize = (var->flags & TDC_SIZEMASK); + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), varsize, "TDC_GETVALUE REPLY"); + // TODO: adjust remove on error (valid reply with invalid data size) + + if (remove <= 0) + break; + + tdcvar_update(var, pkt->data, varsize); + tdcstore_trigger_update(address, pkt->id); + } break; + + case TDC_SETVALUE: { + struct tdc_setvalue_request *pkt = (struct tdc_setvalue_request *)socket_stream->data; + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_SETVALUE"); + if (remove <= 0) + break; + + struct tdc_var *var = tdcstore_get_var(address, pkt->id); + if (var == NULL) { + printf("unknown variable %d\n", pkt->id); + break; + } + + int varsize = (var->flags & TDC_SIZEMASK); + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), varsize, "TDC_GETVALUE REPLY"); + // TODO: adjust remove on error (valid reply with invalid data size) + + /* nothing to do */ + } break; + + case (TDC_SETVALUE | TDC_REPLY): + break; + + case TDC_REQVALUES: { + struct tdc_reqvalues_request *pkt = (struct tdc_reqvalues_request *)socket_stream->data; + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_REQVALUES"); + /* nothing to do */ + } break; + + case (TDC_REQVALUES | TDC_REPLY): { + struct tdc_reqvalues_reply *pkt = (struct tdc_reqvalues_reply *)socket_stream->data; + remove = check_size_helper(socket_stream->len, pkt->size, sizeof(*pkt), 0, "TDC_REQVALUES"); + if (remove <= 0) + break; + + // TODO: output pkt->timestamp, pkt->cnt + } break; + + case TDC_TERMINAL: + case (TDC_TERMINAL | TDC_REPLY): + break; + } + + if (remove != 0) + g_byte_array_remove_range(socket_stream, 0, (remove > 0) ? remove : -remove); + + return remove; +} + +static void tdcparser_read_cb(gpointer data, + gint source, + GdkInputCondition condition) +{ + char buf[256]; + int len = read(socket_fd, buf, sizeof(buf)); + + if (len > 0) { + g_byte_array_append(socket_stream, (guint8 *)buf, len); + + while (socket_stream->len >= 2) { + if (tdcparser_parse() == 0) + break; + } + + } else { + g_warning("gtdc:tdcparser_read_cb:read:%s", g_strerror(errno)); + tdcparser_disconnect(); + } +} + +static void tdcparser_connect_cb(gpointer data, + gint source, + GdkInputCondition condition) +{ + gdk_input_remove(socket_tag); + + if (tcp_connect_error(source) < 0) { + g_warning("gtdc:tdcparser_connect_cb:tcp_connect_error:%s", g_strerror(errno)); + + socket_status_cb(STAT_DISCONNECTED); + close(socket_fd); + + } else { + socket_tag = gdk_input_add(socket_fd, GDK_INPUT_READ, tdcparser_read_cb, NULL); + socket_status_cb(STAT_CONNECTED); + + if (socket_stream == NULL) + socket_stream = g_byte_array_new(); + + else if (socket_stream->len) + g_byte_array_remove_range(socket_stream, 0, socket_stream->len); + + tdcstore_flush(); + tdcparser_send_hello(); + } +} + +void tdcparser_connect(char *addr_str, void (*cb)(int status)) +{ + struct sockaddr_in sa; + parse_sockaddr(addr_str, &sa); + + socket_status_cb = cb; + socket_status_cb(STAT_CONNECTING); + + socket_fd = tcp_connect_nonblock(&sa); + socket_tag = gdk_input_add(socket_fd, GDK_INPUT_WRITE, tdcparser_connect_cb, NULL); +} + +void tdcparser_disconnect(void) +{ + socket_status_cb(STAT_DISCONNECTED); + gdk_input_remove(socket_tag); + close(socket_fd); +} diff --git a/tdc_parser.h b/tdc_parser.h new file mode 100644 index 0000000..207c730 --- /dev/null +++ b/tdc_parser.h @@ -0,0 +1,16 @@ +#ifndef TDC_PARSER_H_ +#define TDC_PARSER_H_ + +enum { + STAT_DISCONNECTED = 0, + STAT_CONNECTING, + STAT_CONNECTED +}; + +int tdcparser_send_getvars(int address); +void tdcparser_send_hello(void); + +void tdcparser_connect(char *addr_str, void (*cb)(int status)); +void tdcparser_disconnect(void); + +#endif /* TDC_PARSER_H_ */ diff --git a/tdcproto.h b/tdc_proto.h similarity index 100% rename from tdcproto.h rename to tdc_proto.h diff --git a/tdc_store.c b/tdc_store.c index 90a2a95..e6df648 100644 --- a/tdc_store.c +++ b/tdc_store.c @@ -1,432 +1,63 @@ -#include #include -#include +#include #include -#include - #include "tdc_store.h" -#include "tdcproto.h" +#include "tdc_variable.h" -#include "variable_tab.h" +#include "gui_variable_tab.h" -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +static char *boardname[8]; +static struct tdc_var *varmap[256]; -static struct tdc_var * var_map[256]; -static GByteArray *stream; - -void tdc_store_get_varvalue(struct tdc_var *var, char *buf, int size, int viewmode) +void tdcstore_set_name(int address, char *name) { - switch ((var->flags & TDC_TYPEMASK) | ((viewmode & 0x01) << 8)) { - case TDC_UNSIGNED: - switch (var->flags & TDC_SIZEMASK) { - case 1: snprintf(buf, size, "%u", var->data_uint8); - break; + if (boardname[address & 0x7] != NULL) + free(boardname[address & 0x7]); - case 2: snprintf(buf, size, "%u", var->data_uint16); - break; - - case 4: snprintf(buf, size, "%u", var->data_uint32); - break; - - case 8: snprintf(buf, size, "%llu", var->data_uint64); - break; - - default: - snprintf(buf, size, "???"); - break; - } - break; - - case TDC_UNSIGNED | 0x100: - switch (var->flags & TDC_SIZEMASK) { - case 1: snprintf(buf, size, "0x%02x", var->data_uint8); - break; - - case 2: snprintf(buf, size, "0x%04x", var->data_uint16); - break; - - case 4: snprintf(buf, size, "0x%08x", var->data_uint32); - break; - - case 8: snprintf(buf, size, "0x%16llx", var->data_uint64); - break; - - default: - snprintf(buf, size, "???"); - break; - } - break; - - case TDC_SIGNED: - switch (var->flags & TDC_SIZEMASK) { - case 1: snprintf(buf, size, "%d", (int8_t)var->data_uint8); - break; - - case 2: snprintf(buf, size, "%d", (int16_t)var->data_uint16); - break; - - case 4: snprintf(buf, size, "%d", (int32_t)var->data_uint32); - break; - - case 8: snprintf(buf, size, "%lld", (int64_t)var->data_uint64); - break; - - default: - snprintf(buf, size, "???"); - break; - } - break; - - case TDC_SIGNED | 0x100: - switch (var->flags & TDC_SIZEMASK) { - case 1: snprintf(buf, size, "0x%02x", (int8_t)var->data_uint8); - break; - - case 2: snprintf(buf, size, "0x%04x", (int16_t)var->data_uint16); - break; - - case 4: snprintf(buf, size, "0x%08x", (int32_t)var->data_uint32); - break; - - case 8: snprintf(buf, size, "0x%16llx", (int64_t)var->data_uint64); - break; - - default: - snprintf(buf, size, "???"); - break; - } - break; - - case TDC_FP: - case TDC_FP | 0x100: - switch (var->flags & TDC_SIZEMASK) { - case sizeof(float): - snprintf(buf, size, "%.8f", var->data_float); - break; - - case sizeof(double): - snprintf(buf, size, "%.12f", var->data_double); - break; - - default: - snprintf(buf, size, "???"); - break; - } - break; - - case TDC_FIXED: - case TDC_FIXED | 0x100: - snprintf(buf, size, "???"); - break; - } + boardname[address & 0x7] = strdup(name); + printf("ADDR%d:%s\n", address, boardname[address & 0x7]); } -void tdc_store_get_vartype(struct tdc_var *var, char *buf, int size) +char * tdcstore_get_name(int address) { - int pos; - int width = (var->flags & TDC_SIZEMASK); + return boardname[address & 0x7]; +} - switch (var->flags & TDC_TYPEMASK) { - case TDC_UNSIGNED: - pos = snprintf(buf, size, "uint%d_t", width * 8); - break; - - case TDC_SIGNED: - pos = snprintf(buf, size, "int%d_t", width * 8); - break; - - case TDC_FP: - if (width == sizeof(float)) - pos = snprintf(buf, size, "float"); - - else if (size == sizeof(double)) - pos = snprintf(buf, size, "double"); - - else - pos = snprintf(buf, size, "fp%d_t", width * 8); - break; - - case TDC_FIXED: - pos = snprintf(buf, size, "fix%d_t", width * 8); - break; - - default: - pos = snprintf(buf, size, "???"); - break; +int tdcstore_set_var(int address, struct tdc_var *var) +{ + if (varmap[var->id] != NULL) { + gui_vartab_remove_var(var); + tdcvar_destroy(varmap[var->id]); } - if (var->flags & TDC_READONLY) - pos = snprintf(buf + pos, size - pos, " (ro)"); + varmap[var->id] = var; + gui_vartab_add_var(var); + + return 0; } -void tdc_store_update_graphlist(void) +struct tdc_var * tdcstore_get_var(int address, int id) { + return varmap[id & 0xFF]; } -static void destroy_var(int id) +void tdcstore_trigger_update(int address, int id) { - g_free(var_map[id]); - var_map[id] = NULL; + gui_vartab_update_var(varmap[id & 0xFF]); } -static void create_var(int id, uint32_t flags, char *name, int len) +void tdcstore_flush(void) { - id &= 0xFF; - - if (var_map[id] != NULL) - destroy_var(id); - - var_map[id] = g_malloc0(sizeof(struct tdc_var) + len + 1); - var_map[id]->id = id; - var_map[id]->flags = flags; - - strncpy(var_map[id]->name, name, len); - var_map[id]->name[len] = '\0'; - - vartab_add_var(var_map[id]); -} - -static void update_var(int id, uint8_t *data, int len) -{ - memcpy(&(var_map[id & 0xFF]->data_uint8), data, len); - - vartab_update_var(var_map[id & 0xFF]); -} - -#if 0 -static char * stream_print(void) -{ - int pos = 0, i = 0, j; - char *buf = g_malloc(stream->len * 4 + 64); - - while (pos < stream->len) { - i += sprintf(buf + i, "%04X: ", pos); - for (j = 0; j < 16; j++) { - if (pos + j < stream->len) - i += sprintf(buf + i, "%02X", stream->data[pos + j]); - else - i += sprintf(buf + i, " "); - - if (j % 2) - buf[i++] = ' '; - } - - for (j = 0; j < 16; j++) { - if (pos + j < stream->len) { - unsigned char val = stream->data[pos + j]; - if (val >= 0x20 && val < 0x80) - buf[i++] = val; - else - buf[i++] = '.'; - } else { - buf[i++] = ' '; - } - } - - pos += 16; - buf[i++] = '\r'; - buf[i++] = '\n'; - } - buf[i] = 0; - return buf; -} -#endif - -static int parse_size_helper(int available, - int packet_size, - int expected_base_size, - int packet_data_size, - const char *name) -{ - /* not enough data in buffer */ - if (available < expected_base_size) { - printf("received incomplete %s\n", name); - return 0; - } - - /* retest, after we know that packet_data_size is valid */ - if (available < (expected_base_size + packet_data_size)) { - printf("received incomplete %s\n", name); - return 0; - } - - /* packet has wrong size */ - if (packet_size != (expected_base_size + packet_data_size)) { - printf("received invalid %s\n", name); - return -1; - } - -// printf("received %s\n", name); - return packet_size; -} - -static int parse(int fd) -{ - int address = (stream->data[0] & TDC_ADDRMASK) >> 4; - - int remove = 1; - - switch (stream->data[0] & (TDC_REPLY | TDC_OPCODEMASK)) { - case TDC_HELLO: { - struct tdc_pkt_header *pkt = (struct tdc_pkt_header *)stream->data; - remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_HELLO"); - /* do nothing, we'll never receive TDC_HELLOs */ - } break; - - case (TDC_HELLO | TDC_REPLY): { - struct tdc_hello_reply *pkt = (struct tdc_hello_reply *)stream->data; - remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_HELLO REPLY"); - if (remove <= 0) - break; - - printf("ADDR%d: '%32s'\n", address, pkt->name); - - struct tdc_pkt_header pkt2; - pkt2.cmd = (address << 4) | TDC_GETVARS; - pkt2.size = sizeof(pkt2); - write(fd, &pkt2, pkt2.size); - - } break; - - case TDC_GETVARS: { - struct tdc_pkt_header *pkt = (struct tdc_pkt_header *)stream->data; - remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVARS"); - /* do nothing, we'll never receive TDC_GETVARSs */ - } break; - - case (TDC_GETVARS | TDC_REPLY): { - struct tdc_getvars_reply *pkt = (struct tdc_getvars_reply *)stream->data; - remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), - pkt->name_len, "TDC_GETVARS REPLY"); - - if (remove <= 0) - break; - - create_var(pkt->id, pkt->flags, pkt->name, pkt->name_len); - printf("create_var(%d, 0x%x, '%s', %d)\n", - pkt->id, var_map[pkt->id]->flags, var_map[pkt->id]->name, pkt->name_len); - } break; - - case TDC_GETVALUE: { - struct tdc_getvalue_request *pkt = (struct tdc_getvalue_request *)stream->data; - remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVALUE"); - /* do nothing, we'll never receive TDC_GETVALUEs */ - } break; - - case (TDC_GETVALUE | TDC_REPLY): { - struct tdc_getvalue_reply *pkt = (struct tdc_getvalue_reply *)stream->data; - - /* check base packet */ - remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_GETVALUE REPLY"); - if (remove <= 0) - break; - - if (var_map[pkt->id & 0xFF] == NULL) { - printf("unknown variable %d\n", pkt->id); - break; - } - - int varsize = (var_map[pkt->id & 0xFF]->flags & TDC_SIZEMASK); - remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), varsize, "TDC_GETVALUE REPLY"); - // TODO: adjust remove on error (valid reply with invalid data size) - - update_var(pkt->id, pkt->data, varsize); - } break; - - case TDC_SETVALUE: { - struct tdc_setvalue_request *pkt = (struct tdc_setvalue_request *)stream->data; - remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_SETVALUE"); - if (remove <= 0) - break; - - if (var_map[pkt->id & 0xFF] == NULL) { - printf("unknown variable %d\n", pkt->id); - break; - } - - int varsize = (var_map[pkt->id & 0xFF]->flags & TDC_SIZEMASK); - remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), varsize, "TDC_GETVALUE REPLY"); - // TODO: adjust remove on error (valid reply with invalid data size) - - /* do nothing, we'll never receive TDC_SETVALUEs */ - } break; - - case (TDC_SETVALUE | TDC_REPLY): - break; - - case TDC_REQVALUES: { - struct tdc_reqvalues_request *pkt = (struct tdc_reqvalues_request *)stream->data; - remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_REQVALUES"); - /* do nothing, we'll never receive TDC_REQVALUESs */ - } break; - - case (TDC_REQVALUES | TDC_REPLY): { - struct tdc_reqvalues_reply *pkt = (struct tdc_reqvalues_reply *)stream->data; - remove = parse_size_helper(stream->len, pkt->size, sizeof(*pkt), 0, "TDC_REQVALUES"); - if (remove <= 0) - break; - - // TODO: output pkt->timestamp, pkt->cnt - } break; - - case TDC_TERMINAL: - case (TDC_TERMINAL | TDC_REPLY): - break; - } - - if (remove != 0) - g_byte_array_remove_range(stream, 0, (remove > 0) ? remove : -remove); - - return remove; -} - -int tdc_parse_data(int fd) -{ - char buf[256]; - int len = read(fd, buf, sizeof(buf)); - - if (len > 0) { - g_byte_array_append(stream, (guint8 *)buf, len); - - while (stream->len >= 2) { - if (parse(fd) == 0) - break; - } - } - - return len; -} - -void tdc_flush_vars(void) -{ - vartab_remove_all_vars(); - int i; - for (i = 0; i < ARRAY_SIZE(var_map); i++) { - if (var_map[i] == NULL) - continue; - - destroy_var(i); + for (i = 0; i < 8; i++) { + free(boardname[i]); + boardname[i] = NULL; } - if (stream->len) - g_byte_array_remove_range(stream, 0, stream->len); -} - -void tdc_send_hello(int fd) -{ - int addr; - for (addr = 1; addr < 8; addr++) { - struct tdc_pkt_header pkt; - pkt.cmd = (addr << 4) | TDC_HELLO; - pkt.size = sizeof(pkt); - - write(fd, &pkt, pkt.size); + for (i = 0; i < 256; i++) { + gui_vartab_remove_var(varmap[i]); + tdcvar_destroy(varmap[i]); + varmap[i] = NULL; } } - -void tdc_init(void) -{ - stream = g_byte_array_new(); -} diff --git a/tdc_store.h b/tdc_store.h index 0a5c158..d048960 100644 --- a/tdc_store.h +++ b/tdc_store.h @@ -1,29 +1,16 @@ #ifndef TDC_STORE_H_ #define TDC_STORE_H_ -#include +#include "tdc_variable.h" -struct tdc_var { - uint32_t id; - uint32_t flags; - union { - uint8_t data_uint8; - uint16_t data_uint16; - uint32_t data_uint32; - uint64_t data_uint64; - float data_float; - double data_double; - }; - char name[0]; -}; +void tdcstore_set_name(int address, char *name); +char * tdcstore_get_name(int address); -void tdc_store_get_varvalue(struct tdc_var *var, char *buf, int size, int viewmode); -void tdc_store_get_vartype(struct tdc_var *var, char *buf, int size); -void tdc_store_update_graphlist(void); +int tdcstore_set_var(int address, struct tdc_var *var); +struct tdc_var * tdcstore_get_var(int address, int id); -int tdc_parse_data(int fd); -void tdc_flush_vars(void); -void tdc_send_hello(int fd); -void tdc_init(void); +void tdcstore_trigger_update(int address, int id); + +void tdcstore_flush(void); #endif /* TDC_STORE_H_ */ diff --git a/tdc_variable.c b/tdc_variable.c new file mode 100644 index 0000000..7e541ac --- /dev/null +++ b/tdc_variable.c @@ -0,0 +1,179 @@ +#include +#include +#include + +#include + +#include "tdc_proto.h" +#include "tdc_variable.h" + +void tdcvar_get_value(struct tdc_var *var, char *buf, int size, int viewmode) +{ + switch ((var->flags & TDC_TYPEMASK) | ((viewmode & 0x01) << 8)) { + case TDC_UNSIGNED: + switch (var->flags & TDC_SIZEMASK) { + case 1: snprintf(buf, size, "%u", var->data_uint8); + break; + + case 2: snprintf(buf, size, "%u", var->data_uint16); + break; + + case 4: snprintf(buf, size, "%u", var->data_uint32); + break; + + case 8: snprintf(buf, size, "%llu", var->data_uint64); + break; + + default: + snprintf(buf, size, "???"); + break; + } + break; + + case TDC_UNSIGNED | 0x100: + switch (var->flags & TDC_SIZEMASK) { + case 1: snprintf(buf, size, "0x%02x", var->data_uint8); + break; + + case 2: snprintf(buf, size, "0x%04x", var->data_uint16); + break; + + case 4: snprintf(buf, size, "0x%08x", var->data_uint32); + break; + + case 8: snprintf(buf, size, "0x%16llx", var->data_uint64); + break; + + default: + snprintf(buf, size, "???"); + break; + } + break; + + case TDC_SIGNED: + switch (var->flags & TDC_SIZEMASK) { + case 1: snprintf(buf, size, "%d", (int8_t)var->data_uint8); + break; + + case 2: snprintf(buf, size, "%d", (int16_t)var->data_uint16); + break; + + case 4: snprintf(buf, size, "%d", (int32_t)var->data_uint32); + break; + + case 8: snprintf(buf, size, "%lld", (int64_t)var->data_uint64); + break; + + default: + snprintf(buf, size, "???"); + break; + } + break; + + case TDC_SIGNED | 0x100: + switch (var->flags & TDC_SIZEMASK) { + case 1: snprintf(buf, size, "0x%02x", (int8_t)var->data_uint8); + break; + + case 2: snprintf(buf, size, "0x%04x", (int16_t)var->data_uint16); + break; + + case 4: snprintf(buf, size, "0x%08x", (int32_t)var->data_uint32); + break; + + case 8: snprintf(buf, size, "0x%16llx", (int64_t)var->data_uint64); + break; + + default: + snprintf(buf, size, "???"); + break; + } + break; + + case TDC_FP: + case TDC_FP | 0x100: + switch (var->flags & TDC_SIZEMASK) { + case sizeof(float): + snprintf(buf, size, "%.8f", var->data_float); + break; + + case sizeof(double): + snprintf(buf, size, "%.12f", var->data_double); + break; + + default: + snprintf(buf, size, "???"); + break; + } + break; + + case TDC_FIXED: + case TDC_FIXED | 0x100: + snprintf(buf, size, "???"); + break; + } +} + +void tdcvar_get_type(struct tdc_var *var, char *buf, int size) +{ + int pos; + int width = (var->flags & TDC_SIZEMASK); + + switch (var->flags & TDC_TYPEMASK) { + case TDC_UNSIGNED: + pos = snprintf(buf, size, "uint%d_t", width * 8); + break; + + case TDC_SIGNED: + pos = snprintf(buf, size, "int%d_t", width * 8); + break; + + case TDC_FP: + if (width == sizeof(float)) + pos = snprintf(buf, size, "float"); + + else if (size == sizeof(double)) + pos = snprintf(buf, size, "double"); + + else + pos = snprintf(buf, size, "fp%d_t", width * 8); + break; + + case TDC_FIXED: + pos = snprintf(buf, size, "fix%d_t", width * 8); + break; + + default: + pos = snprintf(buf, size, "???"); + break; + } + + if (var->flags & TDC_READONLY) + pos = snprintf(buf + pos, size - pos, " (ro)"); +} + +struct tdc_var * tdcvar_create(int id, uint32_t flags, char *name, int len) +{ + struct tdc_var *var = g_malloc0(sizeof(struct tdc_var) + len + 1); + var->id = id & 0xFF; + var->flags = flags; + + strncpy(var->name, name, len); + var->name[len] = '\0'; + + printf("create_var(%d, 0x%x, '%s', %d)\n", var->id, var->flags, var->name, len); + return var; +} + +void tdcvar_update(struct tdc_var *var, uint8_t *data, int len) +{ + if ((var->flags & TDC_SIZEMASK) != len) + return; + + memcpy(&var->data_uint8, data, len); +} + +void tdcvar_destroy(struct tdc_var *var) +{ + g_free(var); +} diff --git a/tdc_variable.h b/tdc_variable.h new file mode 100644 index 0000000..a6f7468 --- /dev/null +++ b/tdc_variable.h @@ -0,0 +1,27 @@ +#ifndef TDC_VARIABLE_H_ +#define TDC_VARIABLE_H_ + +#include + +struct tdc_var { + uint32_t id; + uint32_t flags; + union { + uint8_t data_uint8; + uint16_t data_uint16; + uint32_t data_uint32; + uint64_t data_uint64; + float data_float; + double data_double; + }; + char name[0]; +}; + +void tdcvar_get_value(struct tdc_var *var, char *buf, int size, int viewmode); +void tdcvar_get_type(struct tdc_var *var, char *buf, int size); + +struct tdc_var * tdcvar_create(int id, uint32_t flags, char *name, int len); +void tdcvar_update(struct tdc_var *var, uint8_t *data, int len); +void tdcvar_destroy(struct tdc_var *var); + +#endif /* TDC_VARIABLE_H_ */ diff --git a/variable_tab.h b/variable_tab.h deleted file mode 100644 index d323a09..0000000 --- a/variable_tab.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef VARIABLE_TAB_H_ -#define VARIABLE_TAB_H_ - -#include -#include "tdc_store.h" - -gint variable_tab_init(GtkNotebook *notebook); - -void vartab_add_var(struct tdc_var *var); -void vartab_update_var(struct tdc_var *var); -void vartab_remove_all_vars(void); - -#endif /* VARIABLE_TAB_H_ */