X-Git-Url: http://git.droids-corp.org/?p=protos%2Fxbee-avr.git;a=blobdiff_plain;f=commands.c;h=d67b6515ba1bc60b88620f9c798c9f030f399f3c;hp=a14d098ac6215389da67c68be43260fb0899368e;hb=HEAD;hpb=0f9366b7328777d91aa72f4b92cfcb232969e1ce diff --git a/commands.c b/commands.c index a14d098..d67b651 100644 --- a/commands.c +++ b/commands.c @@ -29,35 +29,37 @@ #include #include #include +#include #include #include #include #include #include +#include +#include -#include "xbee_atcmd.h" -#include "xbee_neighbor.h" -#include "xbee_stats.h" -#include "xbee_proto.h" -#include "xbee.h" - -#include "callout.h" #include "parse_atcmd.h" #include "parse_neighbor.h" #include "parse_monitor.h" +#include "spi_servo.h" #include "rc_proto.h" +#include "xbee_user.h" #include "main.h" #include "cmdline.h" +#include "beep.h" +#include "../fpv-common/i2c_commands.h" +#include "i2c_protocol.h" +#include "eeprom_config.h" /* commands_gen.c */ -extern parse_pgm_inst_t cmd_reset; -extern parse_pgm_inst_t cmd_bootloader; -extern parse_pgm_inst_t cmd_log; -extern parse_pgm_inst_t cmd_log_show; -extern parse_pgm_inst_t cmd_log_type; -extern parse_pgm_inst_t cmd_stack_space; -extern parse_pgm_inst_t cmd_scheduler; +extern const parse_inst_t PROGMEM cmd_reset; +extern const parse_inst_t PROGMEM cmd_bootloader; +extern const parse_inst_t PROGMEM cmd_log; +extern const parse_inst_t PROGMEM cmd_log_show; +extern const parse_inst_t PROGMEM cmd_log_type; +extern const parse_inst_t PROGMEM cmd_stack_space; +extern const parse_inst_t PROGMEM cmd_callout; static int monitor_period_ms = 1000; static int monitor_running = 0; @@ -74,24 +76,30 @@ static struct callout range_event; static int range_count = 100; static int range_cur_count = 0; -static void monitor_cb(struct callout_manager *cm, +static void monitor_cb(struct callout_mgr *cm, struct callout *clt, void *dummy) { + (void)clt; + (void)dummy; + if (monitor_current == NULL) monitor_current = LIST_FIRST(&xbee_monitor_list); - xbeeapp_send_atcmd(monitor_current->atcmd, NULL, 0, 0, NULL, NULL); + /* no rx_cb given: the user must check the monitored values in logs */ + xbeeapp_send_atcmd(monitor_current->atcmd, NULL, 0, NULL, NULL); monitor_current = LIST_NEXT(monitor_current, next); - callout_reset(cm, &monitor_event, - monitor_period_ms / monitor_count, - SINGLE, monitor_cb, NULL); + callout_reschedule(cm, clt, monitor_period_ms / monitor_count); } -static void range_cb(struct callout_manager *cm, +static void range_cb(struct callout_mgr *cm, struct callout *clt, void *dummy) { + struct rc_proto_power_probe power_probe; + struct xbee_msg msg; uint8_t i, mask; - struct rc_proto_range rangepkt; + + (void)clt; + (void)dummy; range_cur_count--; @@ -103,27 +111,82 @@ static void range_cb(struct callout_manager *cm, } range_power = ((range_power + i) & 0x7); - xbeeapp_send_atcmd("PL", &range_power, sizeof(range_power), 0, NULL, NULL); + xbeeapp_send_atcmd("PL", &range_power, sizeof(range_power), NULL, NULL); + + power_probe.type = RC_PROTO_POWER_PROBE; + power_probe.power_level = range_power; - rangepkt.type = RC_PROTO_TYPE_RANGE; - rangepkt.power_level = range_power; + msg.iovlen = 1; + msg.iov[0].buf = &power_probe; + msg.iov[0].len = sizeof(power_probe); - xbeeapp_send_msg(range_dstaddr, &rangepkt, sizeof(rangepkt), 0); + xbeeapp_send_msg(range_dstaddr, &msg, NULL, NULL); if (range_cur_count == 0) { range_running = 0; + callout_stop(cm, clt); return; } - callout_reset(cm, &range_event, - range_period_ms, - SINGLE, range_cb, NULL); + callout_reschedule(cm, clt, range_period_ms); +} + +/* callback invoked when a xbee_send is done */ +static int8_t send_msg_cb(int8_t retcode, void *frame, unsigned len, + void *arg) +{ + struct xbee_xmit_status_hdr *recvframe = frame; + uint8_t *done = arg; + + *done = 1; + if (retcode == XBEE_USER_RETCODE_TIMEOUT) { + printf_P(PSTR("timeout\r\n")); + return retcode; + } + if (retcode == XBEE_USER_RETCODE_BAD_FRAME || + len != sizeof(*recvframe)) { + printf_P(PSTR("invalid frame\r\n")); + return XBEE_USER_RETCODE_BAD_FRAME; + } + + printf_P(PSTR("ok\r\n")); + return XBEE_USER_RETCODE_OK; +} + +/* callback invoked to dump the response to AT command */ +static int8_t dump_xbee_atresp_cb(int8_t retcode, void *frame, unsigned len, + void *arg) +{ + struct xbee_atresp_hdr *recvframe = frame; + char atcmd_str[3]; + char buf[32]; + uint8_t *done = arg; + + *done = 1; + if (retcode == XBEE_USER_RETCODE_TIMEOUT) { + printf_P(PSTR("timeout\r\n")); + return retcode; + } + if (retcode == XBEE_USER_RETCODE_BAD_FRAME || + len < sizeof(*recvframe)) { + printf_P(PSTR("invalid frame\r\n")); + return XBEE_USER_RETCODE_BAD_FRAME; + } + + /* get AT command from frame */ + memcpy(atcmd_str, &recvframe->cmd, 2); + atcmd_str[2] = '\0'; + + atresp_to_str(buf, sizeof(buf), frame, len); + len -= sizeof(*recvframe); + printf_P(PSTR("status ok, len=%d, %s\n"), len, buf); + return XBEE_USER_RETCODE_OK; } /* this structure is filled when cmd_help is parsed successfully */ struct cmd_help_result { fixed_string_t help; - struct xbee_atcmd_pgm *cmd; + struct xbee_atcmd *cmd; }; /* function called when cmd_help is parsed successfully */ @@ -132,6 +195,9 @@ static void cmd_help_parsed(void *parsed_result, void *data) struct cmd_help_result *res = parsed_result; struct xbee_atcmd cmdcopy; int type; + + (void)data; + memcpy_P(&cmdcopy, res->cmd, sizeof(cmdcopy)); type = (cmdcopy.flags & (XBEE_ATCMD_F_READ | XBEE_ATCMD_F_WRITE)); switch (type) { @@ -162,23 +228,23 @@ static void cmd_help_parsed(void *parsed_result, void *data) printf_P(PSTR("%S\r\n"), cmdcopy.help); } -prog_char str_help_help[] = "help"; +const char PROGMEM str_help_help[] = "help"; -parse_pgm_token_string_t cmd_help_help = +const parse_token_string_t PROGMEM cmd_help_help = TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, str_help_help); -parse_pgm_token_atcmd_t cmd_help_atcmd = +const parse_token_atcmd_t PROGMEM cmd_help_atcmd = TOKEN_ATCMD_INITIALIZER(struct cmd_help_result, cmd, &xbee_dev, 0, 0); -prog_char help_help[] = "Help a register using an AT command"; -parse_pgm_inst_t cmd_help = { +const char PROGMEM help_help[] = "Help a register using an AT command"; +const parse_inst_t PROGMEM cmd_help = { .f = cmd_help_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_help, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_help_help, - (prog_void *)&cmd_help_atcmd, + (PGM_P)&cmd_help_help, + (PGM_P)&cmd_help_atcmd, NULL, }, }; @@ -195,30 +261,32 @@ static void cmd_neigh_del_parsed(void *parsed_result, void *data) { struct cmd_neigh_del_result *res = parsed_result; + + (void)data; xbee_neigh_del(xbee_dev, res->neigh); } -prog_char str_neigh_del_neigh[] = "neigh"; -parse_pgm_token_string_t cmd_neigh_del_cmd = +const char PROGMEM str_neigh_del_neigh[] = "neigh"; +const parse_token_string_t PROGMEM cmd_neigh_del_cmd = TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, cmd, str_neigh_del_neigh); -prog_char str_neigh_del_del[] = "del"; -parse_pgm_token_string_t cmd_neigh_del_action = +const char PROGMEM str_neigh_del_del[] = "del"; +const parse_token_string_t PROGMEM cmd_neigh_del_action = TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, action, str_neigh_del_del); -parse_pgm_token_neighbor_t cmd_neigh_del_neigh = +const parse_token_neighbor_t PROGMEM cmd_neigh_del_neigh = TOKEN_NEIGHBOR_INITIALIZER(struct cmd_neigh_del_result, neigh, &xbee_dev); -prog_char help_neigh_del[] = "delete a neighbor"; -parse_pgm_inst_t cmd_neigh_del = { +const char PROGMEM help_neigh_del[] = "delete a neighbor"; +const parse_inst_t PROGMEM cmd_neigh_del = { .f = cmd_neigh_del_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_neigh_del, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_neigh_del_cmd, - (prog_void *)&cmd_neigh_del_action, - (prog_void *)&cmd_neigh_del_neigh, + (PGM_P)&cmd_neigh_del_cmd, + (PGM_P)&cmd_neigh_del_action, + (PGM_P)&cmd_neigh_del_neigh, NULL, }, }; @@ -236,33 +304,35 @@ static void cmd_neigh_add_parsed(void *parsed_result, void *data) { struct cmd_neigh_add_result *res = parsed_result; + + (void)data; if (xbee_neigh_add(xbee_dev, res->name, res->addr) == NULL) printf_P(PSTR("name or addr already exist\r\n")); } -prog_char str_neigh_add_neigh[] = "neigh"; -parse_pgm_token_string_t cmd_neigh_add_cmd = +const char PROGMEM str_neigh_add_neigh[] = "neigh"; +const parse_token_string_t PROGMEM cmd_neigh_add_cmd = TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, cmd, str_neigh_add_neigh); -prog_char str_neigh_add_add[] = "add"; -parse_pgm_token_string_t cmd_neigh_add_action = +const char PROGMEM str_neigh_add_add[] = "add"; +const parse_token_string_t PROGMEM cmd_neigh_add_action = TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, action, str_neigh_add_add); -parse_pgm_token_string_t cmd_neigh_add_name = +const parse_token_string_t PROGMEM cmd_neigh_add_name = TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, name, NULL); -parse_pgm_token_num_t cmd_neigh_add_addr = +const parse_token_num_t PROGMEM cmd_neigh_add_addr = TOKEN_NUM_INITIALIZER(struct cmd_neigh_add_result, addr, UINT64); -prog_char help_neigh_add[] = "add a neighbor"; -parse_pgm_inst_t cmd_neigh_add = { +const char PROGMEM help_neigh_add[] = "add a neighbor"; +const parse_inst_t PROGMEM cmd_neigh_add = { .f = cmd_neigh_add_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_neigh_add, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_neigh_add_cmd, - (prog_void *)&cmd_neigh_add_action, - (prog_void *)&cmd_neigh_add_name, - (prog_void *)&cmd_neigh_add_addr, + (PGM_P)&cmd_neigh_add_cmd, + (PGM_P)&cmd_neigh_add_action, + (PGM_P)&cmd_neigh_add_name, + (PGM_P)&cmd_neigh_add_addr, NULL, }, }; @@ -279,6 +349,8 @@ static void cmd_neigh_list_parsed(void *parsed_result, { struct xbee_neigh *neigh; + (void)parsed_result; + (void)data; LIST_FOREACH(neigh, &xbee_dev->neigh_list, next) { printf_P(PSTR(" %s: 0x%.8"PRIx32"%.8"PRIx32"\r\n"), neigh->name, @@ -287,36 +359,33 @@ static void cmd_neigh_list_parsed(void *parsed_result, } } -prog_char str_neigh_list_neigh[] = "neigh"; -parse_pgm_token_string_t cmd_neigh_list_cmd = +const char PROGMEM str_neigh_list_neigh[] = "neigh"; +const parse_token_string_t PROGMEM cmd_neigh_list_cmd = TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, cmd, str_neigh_list_neigh); -prog_char str_neigh_list_list[] = "list"; -parse_pgm_token_string_t cmd_neigh_list_action = +const char PROGMEM str_neigh_list_list[] = "list"; +const parse_token_string_t PROGMEM cmd_neigh_list_action = TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, action, str_neigh_list_list); -prog_char help_neigh_list[] = "list all knwon neighbors"; -parse_pgm_inst_t cmd_neigh_list = { +const char PROGMEM help_neigh_list[] = "list all knwon neighbors"; +const parse_inst_t PROGMEM cmd_neigh_list = { .f = cmd_neigh_list_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_neigh_list, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_neigh_list_cmd, - (prog_void *)&cmd_neigh_list_action, + (PGM_P)&cmd_neigh_list_cmd, + (PGM_P)&cmd_neigh_list_action, NULL, }, }; - - - /* ************* */ /* this structure is filled when cmd_read is parsed successfully */ struct cmd_read_result { fixed_string_t read; - struct xbee_atcmd_pgm *cmd; + struct xbee_atcmd *cmd; }; /* function called when cmd_read is parsed successfully */ @@ -326,31 +395,34 @@ static void cmd_read_parsed(void *parsed_result, struct cmd_read_result *res = parsed_result; struct xbee_atcmd copy; char cmd[3]; + volatile uint8_t done = 0; + (void)data; memcpy_P(©, res->cmd, sizeof(copy)); memcpy_P(&cmd, copy.name, 2); cmd[2] = '\0'; - xbeeapp_send_atcmd(cmd, NULL, 0, 1, NULL, NULL); + xbeeapp_send_atcmd(cmd, NULL, 0, dump_xbee_atresp_cb, (void *)&done); + while (done == 0); } -prog_char str_read_read[] = "read"; +const char PROGMEM str_read_read[] = "read"; -parse_pgm_token_string_t cmd_read_read = +const parse_token_string_t PROGMEM cmd_read_read = TOKEN_STRING_INITIALIZER(struct cmd_read_result, read, str_read_read); -parse_pgm_token_atcmd_t cmd_read_atcmd = +const parse_token_atcmd_t PROGMEM cmd_read_atcmd = TOKEN_ATCMD_INITIALIZER(struct cmd_read_result, cmd, &xbee_dev, XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ); -prog_char help_read[] = "Read a register using an AT command"; -parse_pgm_inst_t cmd_read = { +const char PROGMEM help_read[] = "Read a register using an AT command"; +const parse_inst_t PROGMEM cmd_read = { .f = cmd_read_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_read, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_read_read, - (prog_void *)&cmd_read_atcmd, + (PGM_P)&cmd_read_read, + (PGM_P)&cmd_read_atcmd, NULL, }, }; @@ -361,7 +433,7 @@ parse_pgm_inst_t cmd_read = { /* this structure is filled when cmd_write is parsed successfully */ struct cmd_write_result { fixed_string_t write; - struct xbee_atcmd_pgm *cmd; + struct xbee_atcmd *cmd; union { uint8_t u8; uint16_t u16; @@ -377,7 +449,9 @@ static void cmd_write_parsed(void *parsed_result, void *data) char cmd[3]; int len; void *param; + volatile uint8_t done = 0; + (void)data; memcpy_P(©, res->cmd, sizeof(copy)); if (copy.flags & XBEE_ATCMD_F_PARAM_NONE) { @@ -404,99 +478,100 @@ static void cmd_write_parsed(void *parsed_result, void *data) } memcpy_P(&cmd, copy.name, 2); cmd[2] = '\0'; - xbeeapp_send_atcmd(cmd, param, len, 1, NULL, NULL); + xbeeapp_send_atcmd(cmd, param, len, dump_xbee_atresp_cb, (void *)&done); + while (done == 0); } -prog_char str_write_none[] = "write"; +const char PROGMEM str_write_none[] = "write"; -parse_pgm_token_string_t cmd_write_write = +const parse_token_string_t PROGMEM cmd_write_write = TOKEN_STRING_INITIALIZER(struct cmd_write_result, write, str_write_none); -parse_pgm_token_atcmd_t cmd_write_none_atcmd = +const parse_token_atcmd_t PROGMEM cmd_write_none_atcmd = TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd, &xbee_dev, XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE, XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE); -prog_char help_write_none[] = "Send an AT command (no argument)"; +const char PROGMEM help_write_none[] = "Send an AT command (no argument)"; -parse_pgm_inst_t cmd_write_none = { +const parse_inst_t PROGMEM cmd_write_none = { .f = cmd_write_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_write_none, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_write_write, - (prog_void *)&cmd_write_none_atcmd, + (PGM_P)&cmd_write_write, + (PGM_P)&cmd_write_none_atcmd, NULL, }, }; -parse_pgm_token_atcmd_t cmd_write_u8_atcmd = +const parse_token_atcmd_t PROGMEM cmd_write_u8_atcmd = TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd, &xbee_dev, XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8, XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8); -parse_pgm_token_num_t cmd_write_u8_u8 = +const parse_token_num_t PROGMEM cmd_write_u8_u8 = TOKEN_NUM_INITIALIZER(struct cmd_write_result, u8, UINT8); -prog_char help_write_u8[] = "Write a 8 bits register using an AT command"; +const char PROGMEM help_write_u8[] = "Write a 8 bits register using an AT command"; -parse_pgm_inst_t cmd_write_u8 = { +const parse_inst_t PROGMEM cmd_write_u8 = { .f = cmd_write_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_write_u8, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_write_write, - (prog_void *)&cmd_write_u8_atcmd, - (prog_void *)&cmd_write_u8_u8, + (PGM_P)&cmd_write_write, + (PGM_P)&cmd_write_u8_atcmd, + (PGM_P)&cmd_write_u8_u8, NULL, }, }; -parse_pgm_token_atcmd_t cmd_write_u16_atcmd = +const parse_token_atcmd_t PROGMEM cmd_write_u16_atcmd = TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd, &xbee_dev, XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16, XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16); -parse_pgm_token_num_t cmd_write_u16_u16 = +const parse_token_num_t PROGMEM cmd_write_u16_u16 = TOKEN_NUM_INITIALIZER(struct cmd_write_result, u16, UINT16); -prog_char help_write_u16[] = "Write a 16 bits register using an AT command"; +const char PROGMEM help_write_u16[] = "Write a 16 bits register using an AT command"; -parse_pgm_inst_t cmd_write_u16 = { +const parse_inst_t PROGMEM cmd_write_u16 = { .f = cmd_write_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_write_u16, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_write_write, - (prog_void *)&cmd_write_u16_atcmd, - (prog_void *)&cmd_write_u16_u16, + (PGM_P)&cmd_write_write, + (PGM_P)&cmd_write_u16_atcmd, + (PGM_P)&cmd_write_u16_u16, NULL, }, }; -parse_pgm_token_atcmd_t cmd_write_u32_atcmd = +const parse_token_atcmd_t PROGMEM cmd_write_u32_atcmd = TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd, &xbee_dev, XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32, XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32); -parse_pgm_token_num_t cmd_write_u32_u32 = +const parse_token_num_t PROGMEM cmd_write_u32_u32 = TOKEN_NUM_INITIALIZER(struct cmd_write_result, u32, UINT32); -prog_char help_write_u32[] = "Write a 32 bits register using an AT command"; +const char PROGMEM help_write_u32[] = "Write a 32 bits register using an AT command"; -parse_pgm_inst_t cmd_write_u32 = { +const parse_inst_t PROGMEM cmd_write_u32 = { .f = cmd_write_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_write_u32, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_write_write, - (prog_void *)&cmd_write_u32_atcmd, - (prog_void *)&cmd_write_u32_u32, + (PGM_P)&cmd_write_write, + (PGM_P)&cmd_write_u32_atcmd, + (PGM_P)&cmd_write_u32_u32, NULL, }, }; @@ -515,31 +590,41 @@ struct cmd_sendmsg_result { static void cmd_sendmsg_parsed(void *parsed_result, void *data) { struct cmd_sendmsg_result *res = parsed_result; - xbeeapp_send_msg(res->addr, res->data, strlen(res->data), 1); + struct xbee_msg msg; + volatile uint8_t done = 0; + + (void)data; + + msg.iovlen = 1; + msg.iov[0].buf = res->data; + msg.iov[0].len = strlen(res->data); + + xbeeapp_send_msg(res->addr, &msg, send_msg_cb, (void *)&done); + while (done == 0); } -prog_char str_sendmsg[] = "sendmsg"; +const char PROGMEM str_sendmsg[] = "sendmsg"; -parse_pgm_token_string_t cmd_sendmsg_sendmsg = +const parse_token_string_t PROGMEM cmd_sendmsg_sendmsg = TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, sendmsg, str_sendmsg); -parse_pgm_token_num_t cmd_sendmsg_addr = +const parse_token_num_t PROGMEM cmd_sendmsg_addr = TOKEN_NUM_INITIALIZER(struct cmd_sendmsg_result, addr, UINT64); -parse_pgm_token_string_t cmd_sendmsg_data = +const parse_token_string_t PROGMEM cmd_sendmsg_data = TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, data, NULL); -prog_char help_sendmsg[] = "Send data to a node using its address"; +const char PROGMEM help_sendmsg[] = "Send data to a node using its address"; -parse_pgm_inst_t cmd_sendmsg = { +const parse_inst_t PROGMEM cmd_sendmsg = { .f = cmd_sendmsg_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_sendmsg, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_sendmsg_sendmsg, - (prog_void *)&cmd_sendmsg_addr, - (prog_void *)&cmd_sendmsg_data, + (PGM_P)&cmd_sendmsg_sendmsg, + (PGM_P)&cmd_sendmsg_addr, + (PGM_P)&cmd_sendmsg_data, NULL, }, }; @@ -557,30 +642,40 @@ struct cmd_sendmsg_name_result { static void cmd_sendmsg_name_parsed(void *parsed_result, void *data) { struct cmd_sendmsg_name_result *res = parsed_result; - xbeeapp_send_msg(res->neigh->addr, res->data, strlen(res->data), 1); + struct xbee_msg msg; + volatile uint8_t done = 0; + + (void)data; + + msg.iovlen = 1; + msg.iov[0].buf = res->data; + msg.iov[0].len = strlen(res->data); + + xbeeapp_send_msg(res->neigh->addr, &msg, send_msg_cb, (void *)&done); + while (done == 0); } -parse_pgm_token_string_t cmd_sendmsg_name_sendmsg_name = +const parse_token_string_t PROGMEM cmd_sendmsg_name_sendmsg_name = TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, sendmsg_name, str_sendmsg); -parse_pgm_token_neighbor_t cmd_sendmsg_name_neigh = +const parse_token_neighbor_t PROGMEM cmd_sendmsg_name_neigh = TOKEN_NEIGHBOR_INITIALIZER(struct cmd_sendmsg_name_result, neigh, &xbee_dev); -parse_pgm_token_string_t cmd_sendmsg_name_data = +const parse_token_string_t PROGMEM cmd_sendmsg_name_data = TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, data, NULL); -prog_char help_sendmsg_name[] = "Send data to a node using its name"; +const char PROGMEM help_sendmsg_name[] = "Send data to a node using its name"; -parse_pgm_inst_t cmd_sendmsg_name = { +const parse_inst_t PROGMEM cmd_sendmsg_name = { .f = cmd_sendmsg_name_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_sendmsg_name, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_sendmsg_name_sendmsg_name, - (prog_void *)&cmd_sendmsg_name_neigh, - (prog_void *)&cmd_sendmsg_name_data, + (PGM_P)&cmd_sendmsg_name_sendmsg_name, + (PGM_P)&cmd_sendmsg_name_neigh, + (PGM_P)&cmd_sendmsg_name_data, NULL, }, }; @@ -599,6 +694,7 @@ static void cmd_range_parsed(void *parsed_result, void *data) { struct cmd_range_result *res = parsed_result; + (void)data; if (!strcmp_P(res->action, PSTR("show"))) { printf_P(PSTR("range infos:\r\n")); printf_P(PSTR(" range period %d\r\n"), range_period_ms); @@ -619,40 +715,40 @@ static void cmd_range_parsed(void *parsed_result, void *data) return; } range_cur_count = range_count; - callout_init(&range_event); - callout_reset(&cm, &range_event, 0, - SINGLE, range_cb, NULL); + callout_init(&range_event, range_cb, NULL, LOW_PRIO); range_running = 1; + callout_schedule(&xbeeboard.intr_cm, + &range_event, 0); /* immediate */ } else if (!strcmp(res->action, "end")) { if (range_running == 0) { printf_P(PSTR("not running\r\n")); return; } + callout_stop(&xbeeboard.intr_cm, &range_event); range_running = 0; - callout_stop(&cm, &range_event); } } -prog_char str_range[] = "range"; -prog_char str_range_tokens[] = "show#start#end"; +const char PROGMEM str_range[] = "range"; +const char PROGMEM str_range_tokens[] = "show#start#end"; -parse_pgm_token_string_t cmd_range_range = +const parse_token_string_t PROGMEM cmd_range_range = TOKEN_STRING_INITIALIZER(struct cmd_range_result, range, str_range); -parse_pgm_token_string_t cmd_range_action = +const parse_token_string_t PROGMEM cmd_range_action = TOKEN_STRING_INITIALIZER(struct cmd_range_result, action, str_range_tokens); -prog_char help_range[] = "start/stop/show current rangeing"; +const char PROGMEM help_range[] = "start/stop/show current rangeing"; -parse_pgm_inst_t cmd_range = { +const parse_inst_t PROGMEM cmd_range = { .f = cmd_range_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_range, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_range_range, - (prog_void *)&cmd_range_action, + (PGM_P)&cmd_range_range, + (PGM_P)&cmd_range_action, NULL, }, }; @@ -671,6 +767,7 @@ static void cmd_range_period_parsed(void *parsed_result, void *data) { struct cmd_range_period_result *res = parsed_result; + (void)data; if (res->period < 10) { printf_P(PSTR("error, minimum period is 10 ms\r\n")); return; @@ -679,27 +776,27 @@ static void cmd_range_period_parsed(void *parsed_result, void *data) range_period_ms = res->period; } -prog_char str_period[] = "period"; +const char PROGMEM str_period[] = "period"; -parse_pgm_token_string_t cmd_range_period_range_period = +const parse_token_string_t PROGMEM cmd_range_period_range_period = TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, range, str_range); -parse_pgm_token_string_t cmd_range_period_action = +const parse_token_string_t PROGMEM cmd_range_period_action = TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, action, str_period); -parse_pgm_token_num_t cmd_range_period_period = +const parse_token_num_t PROGMEM cmd_range_period_period = TOKEN_NUM_INITIALIZER(struct cmd_range_period_result, period, UINT32); -prog_char help_range_period[] = "set range test period"; +const char PROGMEM help_range_period[] = "set range test period"; -parse_pgm_inst_t cmd_range_period = { +const parse_inst_t PROGMEM cmd_range_period = { .f = cmd_range_period_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_range_period, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_range_period_range_period, - (prog_void *)&cmd_range_period_action, - (prog_void *)&cmd_range_period_period, + (PGM_P)&cmd_range_period_range_period, + (PGM_P)&cmd_range_period_action, + (PGM_P)&cmd_range_period_period, NULL, }, }; @@ -717,31 +814,33 @@ struct cmd_range_count_result { static void cmd_range_count_parsed(void *parsed_result, void *data) { struct cmd_range_count_result *res = parsed_result; + + (void)data; range_count = res->count; } -prog_char str_count[] = "count"; +const char PROGMEM str_count[] = "count"; -parse_pgm_token_string_t cmd_range_count_range_count = +const parse_token_string_t PROGMEM cmd_range_count_range_count = TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, range, str_range); -parse_pgm_token_string_t cmd_range_count_action = +const parse_token_string_t PROGMEM cmd_range_count_action = TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, action, str_count); -parse_pgm_token_num_t cmd_range_count_count = +const parse_token_num_t PROGMEM cmd_range_count_count = TOKEN_NUM_INITIALIZER(struct cmd_range_count_result, count, UINT32); -prog_char help_range_count[] = "set range test count"; +const char PROGMEM help_range_count[] = "set range test count"; -parse_pgm_inst_t cmd_range_count = { +const parse_inst_t PROGMEM cmd_range_count = { .f = cmd_range_count_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_range_count, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_range_count_range_count, - (prog_void *)&cmd_range_count_action, - (prog_void *)&cmd_range_count_count, + (PGM_P)&cmd_range_count_range_count, + (PGM_P)&cmd_range_count_action, + (PGM_P)&cmd_range_count_count, NULL, }, }; @@ -759,32 +858,34 @@ struct cmd_range_powermask_result { static void cmd_range_powermask_parsed(void *parsed_result, void *data) { struct cmd_range_powermask_result *res = parsed_result; + + (void)data; range_powermask = res->powermask; } -prog_char str_powermask[] = "powermask"; +const char PROGMEM str_powermask[] = "powermask"; -parse_pgm_token_string_t cmd_range_powermask_range_powermask = +const parse_token_string_t PROGMEM cmd_range_powermask_range_powermask = TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, range, str_range); -parse_pgm_token_string_t cmd_range_powermask_action = +const parse_token_string_t PROGMEM cmd_range_powermask_action = TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, action, str_powermask); -parse_pgm_token_num_t cmd_range_powermask_powermask = +const parse_token_num_t PROGMEM cmd_range_powermask_powermask = TOKEN_NUM_INITIALIZER(struct cmd_range_powermask_result, powermask, UINT8); -prog_char help_range_powermask[] = "set range test powermask"; +const char PROGMEM help_range_powermask[] = "set range test powermask"; -parse_pgm_inst_t cmd_range_powermask = { +const parse_inst_t PROGMEM cmd_range_powermask = { .f = cmd_range_powermask_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_range_powermask, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_range_powermask_range_powermask, - (prog_void *)&cmd_range_powermask_action, - (prog_void *)&cmd_range_powermask_powermask, + (PGM_P)&cmd_range_powermask_range_powermask, + (PGM_P)&cmd_range_powermask_action, + (PGM_P)&cmd_range_powermask_powermask, NULL, }, }; @@ -802,31 +903,33 @@ struct cmd_range_dstaddr_result { static void cmd_range_dstaddr_parsed(void *parsed_result, void *data) { struct cmd_range_dstaddr_result *res = parsed_result; + + (void)data; range_dstaddr = res->dstaddr; } -prog_char str_dstaddr[] = "dstaddr"; +const char PROGMEM str_dstaddr[] = "dstaddr"; -parse_pgm_token_string_t cmd_range_dstaddr_range_dstaddr = +const parse_token_string_t PROGMEM cmd_range_dstaddr_range_dstaddr = TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, range, str_range); -parse_pgm_token_string_t cmd_range_dstaddr_action = +const parse_token_string_t PROGMEM cmd_range_dstaddr_action = TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, action, str_dstaddr); -parse_pgm_token_num_t cmd_range_dstaddr_dstaddr = +const parse_token_num_t PROGMEM cmd_range_dstaddr_dstaddr = TOKEN_NUM_INITIALIZER(struct cmd_range_dstaddr_result, dstaddr, UINT64); -prog_char help_range_dstaddr[] = "set register rangeing dstaddr"; +const char PROGMEM help_range_dstaddr[] = "set register rangeing dstaddr"; -parse_pgm_inst_t cmd_range_dstaddr = { +const parse_inst_t PROGMEM cmd_range_dstaddr = { .f = cmd_range_dstaddr_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_range_dstaddr, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_range_dstaddr_range_dstaddr, - (prog_void *)&cmd_range_dstaddr_action, - (prog_void *)&cmd_range_dstaddr_dstaddr, + (PGM_P)&cmd_range_dstaddr_range_dstaddr, + (PGM_P)&cmd_range_dstaddr_action, + (PGM_P)&cmd_range_dstaddr_dstaddr, NULL, }, }; @@ -846,6 +949,7 @@ static void cmd_monitor_parsed(void *parsed_result, void *data) struct cmd_monitor_result *res = parsed_result; struct monitor_reg *m; + (void)data; if (!strcmp_P(res->action, PSTR("show"))) { printf_P(PSTR("monitor period is %d ms, %d regs in list\r\n"), monitor_period_ms, monitor_count); @@ -861,10 +965,11 @@ static void cmd_monitor_parsed(void *parsed_result, void *data) printf_P(PSTR("no regs to be monitored\r\n")); return; } - callout_init(&monitor_event); - callout_reset(&cm, &monitor_event, 0, SINGLE, monitor_cb, NULL); + callout_init(&monitor_event, monitor_cb, NULL, 1); monitor_running = 1; monitor_current = LIST_FIRST(&xbee_monitor_list); + callout_schedule(&xbeeboard.intr_cm, + &monitor_event, 0); /* immediate */ printf_P(PSTR("monitor cb: %S %s\r\n"), monitor_current->desc, monitor_current->atcmd); @@ -875,30 +980,30 @@ static void cmd_monitor_parsed(void *parsed_result, void *data) printf_P(PSTR("not running\r\n")); return; } + callout_stop(&xbeeboard.intr_cm, &monitor_event); monitor_running = 0; - callout_stop(&cm, &monitor_event); } } -prog_char str_monitor[] = "monitor"; -prog_char str_monitor_tokens[] = "show#start#end"; +const char PROGMEM str_monitor[] = "monitor"; +const char PROGMEM str_monitor_tokens[] = "show#start#end"; -parse_pgm_token_string_t cmd_monitor_monitor = +const parse_token_string_t PROGMEM cmd_monitor_monitor = TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, monitor, str_monitor); -parse_pgm_token_string_t cmd_monitor_action = +const parse_token_string_t PROGMEM cmd_monitor_action = TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, action, str_monitor_tokens); -prog_char help_monitor[] = "start/stop/show current monitoring"; +const char PROGMEM help_monitor[] = "start/stop/show current monitoring"; -parse_pgm_inst_t cmd_monitor = { +const parse_inst_t PROGMEM cmd_monitor = { .f = cmd_monitor_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_monitor, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_monitor_monitor, - (prog_void *)&cmd_monitor_action, + (PGM_P)&cmd_monitor_monitor, + (PGM_P)&cmd_monitor_action, NULL, }, }; @@ -909,7 +1014,7 @@ parse_pgm_inst_t cmd_monitor = { struct cmd_monitor_add_result { fixed_string_t monitor; fixed_string_t action; - struct xbee_atcmd_pgm *cmd; + struct xbee_atcmd *cmd; }; /* function called when cmd_monitor_add is parsed successfully */ @@ -919,6 +1024,7 @@ static void cmd_monitor_add_parsed(void *parsed_result, void *data) struct monitor_reg *m; struct xbee_atcmd copy; + (void)data; memcpy_P(©, res->cmd, sizeof(copy)); LIST_FOREACH(m, &xbee_monitor_list, next) { if (!strcmp_P(m->atcmd, copy.name)) @@ -941,29 +1047,29 @@ static void cmd_monitor_add_parsed(void *parsed_result, void *data) monitor_count ++; } -prog_char str_monitor_add[] = "add"; +const char PROGMEM str_monitor_add[] = "add"; -parse_pgm_token_string_t cmd_monitor_add_monitor_add = +const parse_token_string_t PROGMEM cmd_monitor_add_monitor_add = TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, monitor, str_monitor); -parse_pgm_token_string_t cmd_monitor_add_action = +const parse_token_string_t PROGMEM cmd_monitor_add_action = TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, action, str_monitor_add); -parse_pgm_token_atcmd_t cmd_monitor_add_atcmd = +const parse_token_atcmd_t PROGMEM cmd_monitor_add_atcmd = TOKEN_ATCMD_INITIALIZER(struct cmd_monitor_add_result, cmd, &xbee_dev, XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ); -prog_char help_monitor_add[] = "add a register in monitor list"; +const char PROGMEM help_monitor_add[] = "add a register in monitor list"; -parse_pgm_inst_t cmd_monitor_add = { +const parse_inst_t PROGMEM cmd_monitor_add = { .f = cmd_monitor_add_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_monitor_add, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_monitor_add_monitor_add, - (prog_void *)&cmd_monitor_add_action, - (prog_void *)&cmd_monitor_add_atcmd, + (PGM_P)&cmd_monitor_add_monitor_add, + (PGM_P)&cmd_monitor_add_action, + (PGM_P)&cmd_monitor_add_atcmd, NULL, }, }; @@ -982,6 +1088,7 @@ static void cmd_monitor_period_parsed(void *parsed_result, void *data) { struct cmd_monitor_period_result *res = parsed_result; + (void)data; if (res->period < 100) { printf_P(PSTR("error, minimum period is 100 ms\r\n")); return; @@ -990,28 +1097,28 @@ static void cmd_monitor_period_parsed(void *parsed_result, void *data) monitor_period_ms = res->period; } -prog_char str_monitor_period[] = "period"; +const char PROGMEM str_monitor_period[] = "period"; -parse_pgm_token_string_t cmd_monitor_period_monitor_period = +const parse_token_string_t PROGMEM cmd_monitor_period_monitor_period = TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, monitor, str_monitor); -parse_pgm_token_string_t cmd_monitor_period_action = +const parse_token_string_t PROGMEM cmd_monitor_period_action = TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, action, str_monitor_period); -parse_pgm_token_num_t cmd_monitor_period_period = +const parse_token_num_t PROGMEM cmd_monitor_period_period = TOKEN_NUM_INITIALIZER(struct cmd_monitor_period_result, period, UINT32); -prog_char help_monitor_period[] = "set register monitoring period"; +const char PROGMEM help_monitor_period[] = "set register monitoring period"; -parse_pgm_inst_t cmd_monitor_period = { +const parse_inst_t PROGMEM cmd_monitor_period = { .f = cmd_monitor_period_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_monitor_period, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_monitor_period_monitor_period, - (prog_void *)&cmd_monitor_period_action, - (prog_void *)&cmd_monitor_period_period, + (PGM_P)&cmd_monitor_period_monitor_period, + (PGM_P)&cmd_monitor_period_action, + (PGM_P)&cmd_monitor_period_period, NULL, }, }; @@ -1030,40 +1137,41 @@ static void cmd_monitor_del_parsed(void *parsed_result, void *data) { struct cmd_monitor_del_result *res = parsed_result; + (void)data; monitor_current = LIST_NEXT(res->m, next); LIST_REMOVE(res->m, next); free(res->m); monitor_count --; if (monitor_count == 0) { printf_P(PSTR("Disable monitoring, no more event\r\n")); - callout_stop(&cm, &monitor_event); + callout_stop(&xbeeboard.intr_cm, &monitor_event); monitor_running = 0; return; } } -prog_char str_monitor_del[] = "del"; +const char PROGMEM str_monitor_del[] = "del"; -parse_pgm_token_string_t cmd_monitor_del_monitor_del = +const parse_token_string_t PROGMEM cmd_monitor_del_monitor_del = TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, monitor, str_monitor); -parse_pgm_token_string_t cmd_monitor_del_action = +const parse_token_string_t PROGMEM cmd_monitor_del_action = TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, action, str_monitor_del); -parse_pgm_token_monitor_t cmd_monitor_del_atcmd = +const parse_token_monitor_t PROGMEM cmd_monitor_del_atcmd = TOKEN_MONITOR_INITIALIZER(struct cmd_monitor_del_result, m); -prog_char help_monitor_del[] = "del a register in monitor list"; +const char PROGMEM help_monitor_del[] = "del a register in monitor list"; -parse_pgm_inst_t cmd_monitor_del = { +const parse_inst_t PROGMEM cmd_monitor_del = { .f = cmd_monitor_del_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_monitor_del, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_monitor_del_monitor_del, - (prog_void *)&cmd_monitor_del_action, - (prog_void *)&cmd_monitor_del_atcmd, + (PGM_P)&cmd_monitor_del_monitor_del, + (PGM_P)&cmd_monitor_del_action, + (PGM_P)&cmd_monitor_del_atcmd, NULL, }, }; @@ -1079,23 +1187,28 @@ struct cmd_ping_result { /* function called when cmd_ping is parsed successfully */ static void cmd_ping_parsed(void *parsed_result, void *data) { - xbeeapp_send_atcmd("VL", NULL, 0, 1, NULL, NULL); + volatile uint8_t done = 0; + + (void)parsed_result; + (void)data; + xbeeapp_send_atcmd("VL", NULL, 0, dump_xbee_atresp_cb, (void *)&done); + while (done == 0); } -prog_char str_ping[] = "ping"; +const char PROGMEM str_ping[] = "ping"; -parse_pgm_token_string_t cmd_ping_ping = +const parse_token_string_t PROGMEM cmd_ping_ping = TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping, str_ping); -prog_char help_ping[] = "Send a ping to the xbee device"; +const char PROGMEM help_ping[] = "Send a ping to the xbee device"; -parse_pgm_inst_t cmd_ping = { +const parse_inst_t PROGMEM cmd_ping = { .f = cmd_ping_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_ping, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_ping_ping, + (PGM_P)&cmd_ping_ping, NULL, }, }; @@ -1110,192 +1223,1134 @@ struct cmd_raw_result { /* function called when cmd_raw is parsed successfully */ static void cmd_raw_parsed(void *parsed_result, void *data) { + (void)parsed_result; + (void)data; + + if (range_running || monitor_running) { + printf_P(PSTR("stop running range or monitor first\r\n")); + return; + } printf_P(PSTR("switched to raw mode, CTRL-D to exit\r\n")); rdline_stop(&xbeeboard.rdl); /* don't display prompt when return */ xbee_raw = 1; } -prog_char str_raw[] = "raw"; +const char PROGMEM str_raw[] = "raw"; -parse_pgm_token_string_t cmd_raw_raw = +const parse_token_string_t PROGMEM cmd_raw_raw = TOKEN_STRING_INITIALIZER(struct cmd_raw_result, raw, str_raw); -prog_char help_raw[] = "Switch to raw mode"; +const char PROGMEM help_raw[] = "Switch to raw mode"; -parse_pgm_inst_t cmd_raw = { +const parse_inst_t PROGMEM cmd_raw = { .f = cmd_raw_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ .help_str = help_raw, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_raw_raw, + (PGM_P)&cmd_raw_raw, NULL, }, }; -/* ************* */ +/**********************************************************/ + +/* this structure is filled when cmd_baudrate is parsed successfully */ +struct cmd_baudrate_result { + fixed_string_t arg0; + uint32_t arg1; +}; + +/* function called when cmd_baudrate is parsed successfully */ +static void cmd_baudrate_parsed(void * parsed_result, __attribute__((unused)) void *data) +{ + struct cmd_baudrate_result *res = parsed_result; + struct uart_config c; + + uart_getconf(XBEE_UART, &c); + c.baudrate = res->arg1; + uart_setconf(XBEE_UART, &c); +} + +const char PROGMEM str_baudrate_arg0[] = "baudrate"; +const parse_token_string_t PROGMEM cmd_baudrate_arg0 = + TOKEN_STRING_INITIALIZER(struct cmd_baudrate_result, arg0, + str_baudrate_arg0); +const parse_token_num_t PROGMEM cmd_baudrate_arg1 = + TOKEN_NUM_INITIALIZER(struct cmd_baudrate_result, arg1, + UINT32); + +const char PROGMEM help_baudrate[] = "Change xbee baudrate"; +const parse_inst_t PROGMEM cmd_baudrate = { + .f = cmd_baudrate_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_baudrate, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_baudrate_arg0, + (PGM_P)&cmd_baudrate_arg1, + NULL, + }, +}; + + +/**********************************************************/ + +/* this structure is filled when cmd_beep is parsed successfully */ +struct cmd_beep_result { + fixed_string_t beep; +}; + +/* function called when cmd_beep is parsed successfully */ +static void cmd_beep_parsed(void *parsed_result, void *data) +{ + (void)parsed_result; + (void)data; + + beep(0, 3, 3); + beep(1, 3, 3); + beep(2, 3, 3); + beep(0, 1, 1); + beep(1, 1, 1); + beep(2, 1, 1); +} + +const char PROGMEM str_beep[] = "beep"; +const parse_token_string_t PROGMEM cmd_beep_beep = + TOKEN_STRING_INITIALIZER(struct cmd_beep_result, beep, + str_beep); + +const char PROGMEM help_beep[] = "Send a beep"; + +const parse_inst_t PROGMEM cmd_beep = { + .f = cmd_beep_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_beep, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_beep_beep, + NULL, + }, +}; + +/**********************************************************/ + +/* this structure is filled when cmd_servo is parsed successfully */ +struct cmd_servo_result { + fixed_string_t arg0; + fixed_string_t arg1; + uint16_t num; + uint16_t val; +}; + +/* function called when cmd_servo is parsed successfully */ +static void cmd_servo_parsed(void * parsed_result, void *data) +{ + struct cmd_servo_result *res = parsed_result; + + (void)data; + + if (!strcmp_P(res->arg1, PSTR("set"))) { + if (res->num >= N_SERVO) { + printf_P(PSTR("bad servo num\n")); + return; + } + if (res->val >= 1024) { + printf_P(PSTR("bad servo val\n")); + return; + } + spi_servo_set(res->num, res->val); + } + else if (!strcmp_P(res->arg1, PSTR("bypass"))) { + spi_servo_set_bypass(!!res->val); + } + else if (!strcmp_P(res->arg1, PSTR("ppm"))) { + spi_servo_set_ppm(!!res->val); + } + else if (!strcmp_P(res->arg1, PSTR("show"))) { + spi_servo_dump(); + } +} + +const char PROGMEM str_servo_arg0[] = "servo"; +const parse_token_string_t PROGMEM cmd_servo_arg0 = + TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg0, + str_servo_arg0); +const char PROGMEM str_servo_arg1_set[] = "set"; +const parse_token_string_t PROGMEM cmd_servo_arg1_set = + TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1, + str_servo_arg1_set); +const parse_token_num_t PROGMEM cmd_servo_num = + TOKEN_NUM_INITIALIZER(struct cmd_servo_result, num, + UINT16); +const parse_token_num_t PROGMEM cmd_servo_val = + TOKEN_NUM_INITIALIZER(struct cmd_servo_result, val, + UINT16); + +const char PROGMEM help_servo_set[] = "set servo value"; +const parse_inst_t PROGMEM cmd_servo_set = { + .f = cmd_servo_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_servo_set, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_servo_arg0, + (PGM_P)&cmd_servo_arg1_set, + (PGM_P)&cmd_servo_num, + (PGM_P)&cmd_servo_val, + NULL, + }, +}; + +const char PROGMEM str_servo_arg1_show[] = "show"; +const parse_token_string_t PROGMEM cmd_servo_arg1_show = + TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1, + str_servo_arg1_show); + +const char PROGMEM help_servo_show[] = "read servo and config"; +const parse_inst_t PROGMEM cmd_servo_show = { + .f = cmd_servo_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_servo_show, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_servo_arg0, + (PGM_P)&cmd_servo_arg1_show, + NULL, + }, +}; + +const char PROGMEM str_servo_arg1_bypassppm[] = "bypass#ppm"; +const parse_token_string_t PROGMEM cmd_servo_arg1_bypassppm = + TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1, + str_servo_arg1_bypassppm); + +const char PROGMEM help_servo_bypassppm[] = "change bypass/ppm"; +const parse_inst_t PROGMEM cmd_servo_bypassppm = { + .f = cmd_servo_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_servo_bypassppm, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_servo_arg0, + (PGM_P)&cmd_servo_arg1_bypassppm, + (PGM_P)&cmd_servo_val, + NULL, + }, +}; + +/**********************************************************/ + +/* this structure is filled when cmd_test_spi is parsed successfully */ +struct cmd_test_spi_result { + fixed_string_t arg0; +}; + +static void cmd_test_spi_parsed(void * parsed_result, void *data) +{ + uint8_t i, flags, wait_time = 0; + uint16_t val = 0; + + (void)parsed_result; + (void)data; + + spi_servo_set_bypass(0); + spi_servo_set_ppm(0); + + /* stress test: send many commands, no wait between each servo + * of a series, and a variable delay between series */ + printf_P(PSTR("stress test\r\n")); + while (!cmdline_keypressed()) { + + wait_time++; + if (wait_time > 20) + wait_time = 0; + + IRQ_LOCK(flags); + val = global_ms; + IRQ_UNLOCK(flags); + val >>= 3; + val &= 1023; + + for (i = 0; i < 6; i++) + spi_servo_set(i, val); + + wait_ms(wait_time); + printf_P(PSTR("%4.4d %4.4d %4.4d %4.4d %4.4d %4.4d\r\n"), + spi_servo_get(0), spi_servo_get(1), spi_servo_get(2), + spi_servo_get(3), spi_servo_get(4), spi_servo_get(5)); + } + + printf_P(PSTR("bypass mode, with spi commands in background\r\n")); + spi_servo_set_bypass(1); + + /* test bypass mode */ + while (!cmdline_keypressed()) { + + wait_time++; + if (wait_time > 20) + wait_time = 0; + + IRQ_LOCK(flags); + val = global_ms; + IRQ_UNLOCK(flags); + val >>= 3; + val &= 1023; + + for (i = 0; i < 6; i++) + spi_servo_set(i, val); + + wait_ms(wait_time); + printf_P(PSTR("%4.4d %4.4d %4.4d %4.4d %4.4d %4.4d\r\n"), + spi_servo_get(0), spi_servo_get(1), spi_servo_get(2), + spi_servo_get(3), spi_servo_get(4), spi_servo_get(5)); + } + + printf_P(PSTR("PPM to servo\r\n")); + spi_servo_set_bypass(0); + spi_servo_set_ppm(0); + + /* test PPM to servo (bypass) mode */ + while (!cmdline_keypressed()) { + for (i = 0; i < 6; i++) { + val = spi_servo_get(i); + spi_servo_set(i, val); + } + } + + printf_P(PSTR("PPM to (servo + PPM)\r\n")); + spi_servo_set_bypass(0); + spi_servo_set_ppm(1); + + /* test PPM to servo (bypass) mode */ + while (!cmdline_keypressed()) { + for (i = 0; i < 6; i++) { + val = spi_servo_get(i); + spi_servo_set(i, val); + } + } +} + +const char PROGMEM str_test_spi_arg0[] = "test_spi"; +const parse_token_string_t PROGMEM cmd_test_spi_arg0 = + TOKEN_STRING_INITIALIZER(struct cmd_test_spi_result, arg0, + str_test_spi_arg0); + +const char PROGMEM help_test_spi[] = "Test the spi"; +const parse_inst_t PROGMEM cmd_test_spi = { + .f = cmd_test_spi_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_test_spi, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_test_spi_arg0, + NULL, + }, +}; + +/**********************************************************/ + +/* this structure is filled when cmd_dump_xbee_stats is parsed successfully */ +struct cmd_dump_xbee_stats_result { + fixed_string_t arg0; +}; + +static void cmd_dump_xbee_stats_parsed(void *parsed_result, void *data) +{ + (void)parsed_result; + (void)data; + + xbee_dump_stats(xbee_dev); +} + +const char PROGMEM str_dump_xbee_stats_arg0[] = "dump_xbee_stats"; +const parse_token_string_t PROGMEM cmd_dump_xbee_stats_arg0 = + TOKEN_STRING_INITIALIZER(struct cmd_dump_xbee_stats_result, arg0, + str_dump_xbee_stats_arg0); + +const char PROGMEM help_dump_xbee_stats[] = "Test the spi"; +const parse_inst_t PROGMEM cmd_dump_xbee_stats = { + .f = cmd_dump_xbee_stats_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_dump_xbee_stats, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_dump_xbee_stats_arg0, + NULL, + }, +}; + +/**********************************************************/ + +/* this structure is filled when cmd_rc_proto_stats is parsed successfully */ +struct cmd_rc_proto_stats_result { + fixed_string_t arg0; + fixed_string_t arg1; +}; + +static void cmd_rc_proto_stats_parsed(void *parsed_result, void *data) +{ + struct cmd_rc_proto_stats_result *res = parsed_result; + (void)data; + + if (!strcmp(res->arg1, "show")) + rc_proto_dump_stats(); + else /* reset */ + rc_proto_reset_stats(); +} + +const char PROGMEM str_rc_proto_stats_arg0[] = "rc_proto_stats"; +const parse_token_string_t PROGMEM cmd_rc_proto_stats_arg0 = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_stats_result, arg0, + str_rc_proto_stats_arg0); +const char PROGMEM str_rc_proto_stats_arg1[] = "show#reset"; +const parse_token_string_t PROGMEM cmd_rc_proto_stats_arg1 = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_stats_result, arg1, + str_rc_proto_stats_arg1); + +const char PROGMEM help_rc_proto_stats[] = "dump rc_proto stats"; +const parse_inst_t PROGMEM cmd_rc_proto_stats = { + .f = cmd_rc_proto_stats_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_rc_proto_stats, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_rc_proto_stats_arg0, + (PGM_P)&cmd_rc_proto_stats_arg1, + NULL, + }, +}; + +/**********************************************************/ + +/* this structure is filled when cmd_rc_proto_timers is parsed successfully */ +struct cmd_rc_proto_timers_result { + fixed_string_t arg0; + fixed_string_t arg1; + uint16_t servo_min; + uint16_t servo_max; + uint16_t power_probe; + uint16_t autobypass; +}; + +static void cmd_rc_proto_timers_parsed(void *parsed_result, void *data) +{ + struct cmd_rc_proto_timers_result *res = parsed_result; + (void)data; + + if (!strcmp_P(res->arg1, PSTR("set"))) { + rc_proto_timers.send_servo_min_ms = res->servo_min; + rc_proto_timers.send_servo_max_ms = res->servo_max; + rc_proto_timers.send_power_probe_ms = res->power_probe; + rc_proto_timers.autobypass_ms = res->autobypass; + } + + printf_P(PSTR("rc_proto_timers: min=%d, max=%d, " + "power_probe=%d autobypass=%d\n"), + rc_proto_timers.send_servo_min_ms, + rc_proto_timers.send_servo_max_ms, + rc_proto_timers.send_power_probe_ms, + rc_proto_timers.autobypass_ms); +} -/* this structure is filled when cmd_dump is parsed successfully */ -struct cmd_dump_result { - fixed_string_t dump; - fixed_string_t onoff; +const char PROGMEM str_rc_proto_timers_arg0[] = "rc_proto_timers"; +const parse_token_string_t PROGMEM cmd_rc_proto_timers_arg0 = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_timers_result, arg0, + str_rc_proto_timers_arg0); +const char PROGMEM str_rc_proto_timers_arg1[] = "set"; +const parse_token_string_t PROGMEM cmd_rc_proto_timers_arg1 = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_timers_result, arg1, + str_rc_proto_timers_arg1); +const parse_token_num_t PROGMEM cmd_rc_proto_timers_servo_min = + TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, servo_min, + UINT16); +const parse_token_num_t PROGMEM cmd_rc_proto_timers_servo_max = + TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, servo_max, + UINT16); +const parse_token_num_t PROGMEM cmd_rc_proto_timers_power_probe = + TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, power_probe, + UINT16); +const parse_token_num_t PROGMEM cmd_rc_proto_timers_autobypass = + TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, autobypass, + UINT16); + +const char PROGMEM help_rc_proto_timers[] = "set rc_proto_timers (servo_min, " + "servo_max, pow_probe, autobypass)"; +const parse_inst_t PROGMEM cmd_rc_proto_timers = { + .f = cmd_rc_proto_timers_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_rc_proto_timers, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_rc_proto_timers_arg0, + (PGM_P)&cmd_rc_proto_timers_arg1, + (PGM_P)&cmd_rc_proto_timers_servo_min, + (PGM_P)&cmd_rc_proto_timers_servo_max, + (PGM_P)&cmd_rc_proto_timers_power_probe, + (PGM_P)&cmd_rc_proto_timers_autobypass, + NULL, + }, +}; + +const char PROGMEM str_rc_proto_timers_show_arg1[] = "show"; +const parse_token_string_t PROGMEM cmd_rc_proto_timers_show_arg1 = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_timers_result, arg1, + str_rc_proto_timers_show_arg1); + +const char PROGMEM help_rc_proto_timers_show[] = "show rc_proto timers value"; +const parse_inst_t PROGMEM cmd_rc_proto_timers_show = { + .f = cmd_rc_proto_timers_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_rc_proto_timers_show, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_rc_proto_timers_arg0, + (PGM_P)&cmd_rc_proto_timers_show_arg1, + NULL, + }, +}; + +/**********************************************************/ + +/* this structure is filled when cmd_rc_proto_mode is parsed successfully */ +struct cmd_rc_proto_mode_result { + fixed_string_t arg0; + fixed_string_t cmd; + fixed_string_t val; +}; + +static void cmd_rc_proto_mode_parsed(void *parsed_result, void *data) +{ + struct cmd_rc_proto_mode_result *res = parsed_result; + (void)data; + uint8_t flags; + uint8_t on = 0; + + flags = rc_proto_get_mode(); + if (!strcmp_P(res->val, PSTR("on"))) + on = 1; + + if (!strcmp_P(res->cmd, PSTR("rx_copy_spi"))) { + if (on == 1) + flags |= RC_PROTO_FLAGS_RX_COPY_SPI; + else + flags &= ~RC_PROTO_FLAGS_RX_COPY_SPI; + } + else if (!strcmp_P(res->cmd, PSTR("rx_autobypass"))) { + if (on == 1) + flags |= RC_PROTO_FLAGS_RX_AUTOBYPASS; + else + flags &= ~RC_PROTO_FLAGS_RX_AUTOBYPASS; + } + else if (!strcmp_P(res->cmd, PSTR("tx_stats"))) { + if (on == 1) + flags |= RC_PROTO_FLAGS_TX_STATS; + else + flags &= ~RC_PROTO_FLAGS_TX_STATS; + } + else if (!strcmp_P(res->cmd, PSTR("tx_power_probe"))) { + if (on == 1) + flags |= RC_PROTO_FLAGS_TX_POW_PROBE; + else + flags &= ~RC_PROTO_FLAGS_TX_POW_PROBE; + } + else if (!strcmp_P(res->cmd, PSTR("compute_best_pow"))) { + if (on == 1) + flags |= RC_PROTO_FLAGS_COMPUTE_BEST_POW; + else + flags &= ~RC_PROTO_FLAGS_COMPUTE_BEST_POW; + } + else if (!strcmp_P(res->cmd, PSTR("tx"))) { + flags &= ~RC_PROTO_FLAGS_TX_MASK; + if (!strcmp_P(res->val, PSTR("bypass"))) + flags |= RC_PROTO_FLAGS_TX_BYPASS; + else if (!strcmp_P(res->val, PSTR("copy_spi"))) + flags |= RC_PROTO_FLAGS_TX_COPY_SPI; + } + rc_proto_set_mode(flags); + + /* dump state */ + if ((flags & RC_PROTO_FLAGS_TX_MASK) == RC_PROTO_FLAGS_TX_OFF) + printf_P(PSTR("rc_proto_mode tx off\n")); + else if ((flags & RC_PROTO_FLAGS_TX_MASK) == RC_PROTO_FLAGS_TX_BYPASS) + printf_P(PSTR("rc_proto_mode tx bypass\n")); + else if ((flags & RC_PROTO_FLAGS_TX_MASK) == RC_PROTO_FLAGS_TX_COPY_SPI) + printf_P(PSTR("rc_proto_mode tx copy_spi\n")); + printf_P(PSTR("rc_proto_mode rx_copy_spi %s\n"), + (flags & RC_PROTO_FLAGS_RX_COPY_SPI) ? "on" : "off"); + printf_P(PSTR("rc_proto_mode rx_autobypass %s\n"), + (flags & RC_PROTO_FLAGS_RX_AUTOBYPASS) ? "on" : "off"); + printf_P(PSTR("rc_proto_mode tx_stats %s\n"), + (flags & RC_PROTO_FLAGS_TX_STATS) ? "on" : "off"); + printf_P(PSTR("rc_proto_mode tx_power_probe %s\n"), + (flags & RC_PROTO_FLAGS_TX_POW_PROBE) ? "on" : "off"); + printf_P(PSTR("rc_proto_mode compute_best_pow %s\n"), + (flags & RC_PROTO_FLAGS_COMPUTE_BEST_POW) ? "on" : "off"); +} + +const char PROGMEM str_rc_proto_mode_arg0[] = "rc_proto_mode"; +const parse_token_string_t PROGMEM cmd_rc_proto_mode_arg0 = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, arg0, + str_rc_proto_mode_arg0); + +const char PROGMEM str_rc_proto_mode_cmd[] = + "rx_copy_spi#rx_autobypass#tx_stats#tx_power_probe#compute_best_pow"; +const parse_token_string_t PROGMEM cmd_rc_proto_mode_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, cmd, + str_rc_proto_mode_cmd); + +const char PROGMEM str_rc_proto_mode_onoff[] = "on#off"; +const parse_token_string_t PROGMEM cmd_rc_proto_mode_onoff = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, val, + str_rc_proto_mode_onoff); + +const char PROGMEM help_rc_proto_mode[] = "Set rc proto behavior"; +const parse_inst_t PROGMEM cmd_rc_proto_mode = { + .f = cmd_rc_proto_mode_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_rc_proto_mode, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_rc_proto_mode_arg0, + (PGM_P)&cmd_rc_proto_mode_cmd, + (PGM_P)&cmd_rc_proto_mode_onoff, + NULL, + }, +}; + +const char PROGMEM str_rc_proto_mode_cmd2[] = "tx"; +const parse_token_string_t PROGMEM cmd_rc_proto_mode_cmd2 = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, cmd, + str_rc_proto_mode_cmd2); + +const char PROGMEM str_rc_proto_mode_val[] = "off#bypass#copy_spi"; +const parse_token_string_t PROGMEM cmd_rc_proto_mode_val = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, val, + str_rc_proto_mode_val); + +const parse_inst_t PROGMEM cmd_rc_proto_mode2 = { + .f = cmd_rc_proto_mode_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_rc_proto_mode, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_rc_proto_mode_arg0, + (PGM_P)&cmd_rc_proto_mode_cmd2, + (PGM_P)&cmd_rc_proto_mode_val, + NULL, + }, +}; + +const char PROGMEM str_rc_proto_mode_cmd3[] = "show"; +const parse_token_string_t PROGMEM cmd_rc_proto_mode_cmd3 = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, cmd, + str_rc_proto_mode_cmd3); + +const parse_inst_t PROGMEM cmd_rc_proto_mode3 = { + .f = cmd_rc_proto_mode_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_rc_proto_mode, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_rc_proto_mode_arg0, + (PGM_P)&cmd_rc_proto_mode_cmd3, + NULL, + }, }; -/* function called when cmd_dump is parsed successfully */ -static void cmd_dump_parsed(void *parsed_result, void *data) +/**********************************************************/ + +/* this structure is filled when cmd_rc_proto_hello is parsed successfully */ +struct cmd_rc_proto_hello_result { + fixed_string_t rc_proto_hello; + uint64_t addr; + struct xbee_neigh *neigh; + uint16_t period; + uint16_t count; + fixed_string_t data; +}; + +/* function called when cmd_rc_proto_hello is parsed successfully */ +static void cmd_rc_proto_hello_parsed(void *parsed_result, void *use_neigh) { - struct cmd_dump_result *res = parsed_result; - if (!strcmp(res->onoff, "on")) - xbee_hexdump = 1; + struct cmd_rc_proto_hello_result *res = parsed_result; + uint16_t now, next, diff; + uint8_t flags; + uint64_t addr; + + if (use_neigh) + addr = res->neigh->addr; else - xbee_hexdump = 0; + addr = res->addr; + + IRQ_LOCK(flags); + now = global_ms; + IRQ_UNLOCK(flags); + + next = now; + + while (!cmdline_keypressed() && res->count != 0) { + IRQ_LOCK(flags); + now = global_ms; + IRQ_UNLOCK(flags); + + diff = now - next; + if (diff < res->period) + continue; + + rc_proto_send_hello(addr, res->data, strlen(res->data), -1); + next += res->period; + res->count--; + } } -prog_char str_dump[] = "dump"; -prog_char str_dump_onoff[] = "on#off"; +const char PROGMEM str_rc_proto_hello[] = "rc_proto_hello"; + +const parse_token_string_t PROGMEM cmd_rc_proto_hello_rc_proto_hello = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_hello_result, rc_proto_hello, + str_rc_proto_hello); -parse_pgm_token_string_t cmd_dump_dump = - TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump, - str_dump); +const parse_token_num_t PROGMEM cmd_rc_proto_hello_addr = + TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_hello_result, addr, UINT64); -parse_pgm_token_string_t cmd_dump_onoff = - TOKEN_STRING_INITIALIZER(struct cmd_dump_result, onoff, - str_dump_onoff); +const parse_token_num_t PROGMEM cmd_rc_proto_hello_period = + TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_hello_result, period, UINT16); -prog_char help_dump[] = "enable/disable hexdump of received packets"; +const parse_token_num_t PROGMEM cmd_rc_proto_hello_count = + TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_hello_result, count, UINT16); -parse_pgm_inst_t cmd_dump = { - .f = cmd_dump_parsed, /* function to call */ +const parse_token_string_t PROGMEM cmd_rc_proto_hello_data = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_hello_result, data, NULL); + +const char PROGMEM help_rc_proto_hello[] = + "Send hello msg to a node: addr, period_ms, count, str"; + +const parse_inst_t PROGMEM cmd_rc_proto_hello = { + .f = cmd_rc_proto_hello_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ - .help_str = help_dump, + .help_str = help_rc_proto_hello, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_dump_dump, - (prog_void *)&cmd_dump_onoff, + (PGM_P)&cmd_rc_proto_hello_rc_proto_hello, + (PGM_P)&cmd_rc_proto_hello_addr, + (PGM_P)&cmd_rc_proto_hello_period, + (PGM_P)&cmd_rc_proto_hello_count, + (PGM_P)&cmd_rc_proto_hello_data, NULL, }, }; -/* ************* */ +const parse_token_neighbor_t PROGMEM cmd_rc_proto_hello_neigh = + TOKEN_NEIGHBOR_INITIALIZER(struct cmd_rc_proto_hello_result, neigh, + &xbee_dev); -/* this structure is filled when cmd_debug is parsed successfully */ -struct cmd_debug_result { - fixed_string_t debug; - fixed_string_t onoff; +const parse_inst_t PROGMEM cmd_rc_proto_hello_name = { + .f = cmd_rc_proto_hello_parsed, /* function to call */ + .data = (void *)1, /* 2nd arg of func */ + .help_str = help_rc_proto_hello, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_rc_proto_hello_rc_proto_hello, + (PGM_P)&cmd_rc_proto_hello_neigh, + (PGM_P)&cmd_rc_proto_hello_period, + (PGM_P)&cmd_rc_proto_hello_count, + (PGM_P)&cmd_rc_proto_hello_data, + NULL, + }, }; -/* function called when cmd_debug is parsed successfully */ -static void cmd_debug_parsed(void *parsed_result, void *data) +/**********************************************************/ + +/* this structure is filled when cmd_rc_proto_echo is parsed successfully */ +struct cmd_rc_proto_echo_result { + fixed_string_t rc_proto_echo; + uint64_t addr; + struct xbee_neigh *neigh; + uint16_t period; + uint16_t count; + fixed_string_t data; +}; + +/* function called when cmd_rc_proto_echo is parsed successfully */ +static void cmd_rc_proto_echo_parsed(void *parsed_result, void *use_neigh) { - struct cmd_debug_result *res = parsed_result; - if (!strcmp(res->onoff, "on")) - xbee_debug = 1; + struct cmd_rc_proto_echo_result *res = parsed_result; + uint16_t now, next, diff; + uint8_t flags; + uint64_t addr; + + if (use_neigh) + addr = res->neigh->addr; else - xbee_debug = 0; + addr = res->addr; + + IRQ_LOCK(flags); + now = global_ms; + IRQ_UNLOCK(flags); + + next = now; + + while (!cmdline_keypressed() && res->count != 0) { + IRQ_LOCK(flags); + now = global_ms; + IRQ_UNLOCK(flags); + + diff = now - next; + if (diff < res->period) + continue; + + rc_proto_send_echo_req(addr, res->data, strlen(res->data), -1); + next += res->period; + res->count--; + } } -prog_char str_debug[] = "debug"; -prog_char str_debug_onoff[] = "on#off"; +const char PROGMEM str_rc_proto_echo[] = "rc_proto_echo"; -parse_pgm_token_string_t cmd_debug_debug = - TOKEN_STRING_INITIALIZER(struct cmd_debug_result, debug, - str_debug); +const parse_token_string_t PROGMEM cmd_rc_proto_echo_rc_proto_echo = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_echo_result, rc_proto_echo, + str_rc_proto_echo); -parse_pgm_token_string_t cmd_debug_onoff = - TOKEN_STRING_INITIALIZER(struct cmd_debug_result, onoff, - str_debug_onoff); +const parse_token_num_t PROGMEM cmd_rc_proto_echo_addr = + TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_echo_result, addr, UINT64); -prog_char help_debug[] = "enable/disable additionnal debug"; +const parse_token_num_t PROGMEM cmd_rc_proto_echo_period = + TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_echo_result, period, UINT16); -parse_pgm_inst_t cmd_debug = { - .f = cmd_debug_parsed, /* function to call */ +const parse_token_num_t PROGMEM cmd_rc_proto_echo_count = + TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_echo_result, count, UINT16); + +const parse_token_string_t PROGMEM cmd_rc_proto_echo_data = + TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_echo_result, data, NULL); + +const char PROGMEM help_rc_proto_echo[] = + "Send echo msg to a node: addr, period_ms, count, str"; + +const parse_inst_t PROGMEM cmd_rc_proto_echo = { + .f = cmd_rc_proto_echo_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ - .help_str = help_debug, + .help_str = help_rc_proto_echo, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_rc_proto_echo_rc_proto_echo, + (PGM_P)&cmd_rc_proto_echo_addr, + (PGM_P)&cmd_rc_proto_echo_period, + (PGM_P)&cmd_rc_proto_echo_count, + (PGM_P)&cmd_rc_proto_echo_data, + NULL, + }, +}; + +const parse_token_neighbor_t PROGMEM cmd_rc_proto_echo_neigh = + TOKEN_NEIGHBOR_INITIALIZER(struct cmd_rc_proto_echo_result, neigh, + &xbee_dev); + +const parse_inst_t PROGMEM cmd_rc_proto_echo_name = { + .f = cmd_rc_proto_echo_parsed, /* function to call */ + .data = (void *)1, /* 2nd arg of func */ + .help_str = help_rc_proto_echo, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_debug_debug, - (prog_void *)&cmd_debug_onoff, + (PGM_P)&cmd_rc_proto_echo_rc_proto_echo, + (PGM_P)&cmd_rc_proto_echo_neigh, + (PGM_P)&cmd_rc_proto_echo_period, + (PGM_P)&cmd_rc_proto_echo_count, + (PGM_P)&cmd_rc_proto_echo_data, NULL, }, }; -#ifndef USE_USB /**********************************************************/ -/* this structure is filled when cmd_baudrate is parsed successfully */ -struct cmd_baudrate_result { +/* this structure is filled when cmd_test_eeprom_config is parsed successfully */ +struct cmd_test_eeprom_config_result { fixed_string_t arg0; - uint32_t arg1; }; -/* function called when cmd_baudrate is parsed successfully */ -static void cmd_baudrate_parsed(void * parsed_result, __attribute__((unused)) void *data) +static void cmd_test_eeprom_config_parsed(void *parsed_result, void *data) { - struct cmd_baudrate_result *res = parsed_result; - struct uart_config c; + (void)parsed_result; + (void)data; + + eeprom_dump_cmds(); + eeprom_append_cmd("salut1\n"); + eeprom_dump_cmds(); + eeprom_append_cmd("salut2\n"); + eeprom_append_cmd("salut3\n"); + eeprom_append_cmd("salut4\n"); + eeprom_dump_cmds(); + eeprom_insert_cmd_before("coin\n", 0); + eeprom_insert_cmd_before("coin2\n", 2); + eeprom_dump_cmds(); + eeprom_delete_cmd(2); + eeprom_delete_cmd(0); + eeprom_dump_cmds(); +} - uart_getconf(XBEE_UART, &c); - c.baudrate = res->arg1; - uart_setconf(XBEE_UART, &c); +const char PROGMEM str_test_eeprom_config_arg0[] = "test_eeprom_config"; +const parse_token_string_t PROGMEM cmd_test_eeprom_config_arg0 = + TOKEN_STRING_INITIALIZER(struct cmd_test_eeprom_config_result, arg0, + str_test_eeprom_config_arg0); + +const char PROGMEM help_test_eeprom_config[] = "Test the eeprom configuration"; +const parse_inst_t PROGMEM cmd_test_eeprom_config = { + .f = cmd_test_eeprom_config_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_test_eeprom_config, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_test_eeprom_config_arg0, + NULL, + }, +}; + +/* ************* */ + +struct cmd_eeprom_del_result { + fixed_string_t cmd; + fixed_string_t action; + uint8_t n; +}; + +static void cmd_eeprom_del_parsed(void *parsed_result, + void *data) +{ + struct cmd_eeprom_del_result *res = parsed_result; + + (void)data; + if (eeprom_delete_cmd(res->n) < 0) + printf_P(PSTR("cannot delete command\n")); + eeprom_dump_cmds(); } -prog_char str_baudrate_arg0[] = "baudrate"; -parse_pgm_token_string_t cmd_baudrate_arg0 = - TOKEN_STRING_INITIALIZER(struct cmd_baudrate_result, arg0, - str_baudrate_arg0); -parse_pgm_token_num_t cmd_baudrate_arg1 = - TOKEN_NUM_INITIALIZER(struct cmd_baudrate_result, arg1, - UINT32); +const char PROGMEM str_eeprom_del_eeprom[] = "eeprom"; +const parse_token_string_t PROGMEM cmd_eeprom_del_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_eeprom_del_result, cmd, + str_eeprom_del_eeprom); +const char PROGMEM str_eeprom_del_del[] = "del"; +const parse_token_string_t PROGMEM cmd_eeprom_del_action = + TOKEN_STRING_INITIALIZER(struct cmd_eeprom_del_result, action, + str_eeprom_del_del); +const parse_token_num_t PROGMEM cmd_eeprom_del_num = + TOKEN_NUM_INITIALIZER(struct cmd_eeprom_del_result, n, + UINT8); -prog_char help_baudrate[] = "Change xbee baudrate"; -parse_pgm_inst_t cmd_baudrate = { - .f = cmd_baudrate_parsed, /* function to call */ +const char PROGMEM help_eeprom_del[] = "delete an eeprom init command"; +const parse_inst_t PROGMEM cmd_eeprom_del = { + .f = cmd_eeprom_del_parsed, /* function to call */ .data = NULL, /* 2nd arg of func */ - .help_str = help_baudrate, + .help_str = help_eeprom_del, .tokens = { /* token list, NULL terminated */ - (prog_void *)&cmd_baudrate_arg0, - (prog_void *)&cmd_baudrate_arg1, + (PGM_P)&cmd_eeprom_del_cmd, + (PGM_P)&cmd_eeprom_del_action, + (PGM_P)&cmd_eeprom_del_num, NULL, }, }; -#endif +/* ************* */ + +struct cmd_eeprom_add_result { + fixed_string_t cmd; + fixed_string_t action; + uint8_t n; +}; + +static void cmd_eeprom_add_parsed(void *parsed_result, + void *data) +{ + struct cmd_eeprom_add_result *res = parsed_result; + struct rdline rdl; + const char *buffer; + int8_t ret; + int16_t c; + + rdline_init(&rdl, cmdline_write_char, NULL, NULL); + rdline_newline(&rdl, "> "); + + while (1) { + c = cmdline_dev_recv(NULL); + if (c < 0) + continue; + + ret = rdline_char_in(&rdl, c); + if (ret == -2) { + printf_P(PSTR("abort\n")); + return; + } + if (ret == 1) + break; + } + + buffer = rdline_get_buffer(&rdl); + if (data == NULL) + eeprom_insert_cmd_before(buffer, res->n); + else + eeprom_append_cmd(buffer); + eeprom_dump_cmds(); +} + +const char PROGMEM str_eeprom_add_eeprom[] = "eeprom"; +const parse_token_string_t PROGMEM cmd_eeprom_add_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_eeprom_add_result, cmd, + str_eeprom_add_eeprom); +const char PROGMEM str_eeprom_add_add[] = "add"; +const parse_token_string_t PROGMEM cmd_eeprom_add_action = + TOKEN_STRING_INITIALIZER(struct cmd_eeprom_add_result, action, + str_eeprom_add_add); +const parse_token_num_t PROGMEM cmd_eeprom_add_num = + TOKEN_NUM_INITIALIZER(struct cmd_eeprom_add_result, n, + UINT8); + +const char PROGMEM help_eeprom_add[] = "insert an eeprom init command"; +const parse_inst_t PROGMEM cmd_eeprom_add = { + .f = cmd_eeprom_add_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_eeprom_add, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_eeprom_add_cmd, + (PGM_P)&cmd_eeprom_add_action, + (PGM_P)&cmd_eeprom_add_num, + NULL, + }, +}; + +const char PROGMEM help_eeprom_add2[] = "append an eeprom init command"; +const parse_inst_t PROGMEM cmd_eeprom_add2 = { + .f = cmd_eeprom_add_parsed, /* function to call */ + .data = (void *)1, /* 2nd arg of func */ + .help_str = help_eeprom_add2, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_eeprom_add_cmd, + (PGM_P)&cmd_eeprom_add_action, + NULL, + }, +}; + +/* ************* */ + +struct cmd_eeprom_list_result { + fixed_string_t cmd; + fixed_string_t action; +}; + +static void cmd_eeprom_list_parsed(void *parsed_result, + void *data) +{ + (void)parsed_result; + (void)data; + eeprom_dump_cmds(); +} + +const char PROGMEM str_eeprom_list_eeprom[] = "eeprom"; +const parse_token_string_t PROGMEM cmd_eeprom_list_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_eeprom_list_result, cmd, + str_eeprom_list_eeprom); +const char PROGMEM str_eeprom_list_list[] = "list"; +const parse_token_string_t PROGMEM cmd_eeprom_list_action = + TOKEN_STRING_INITIALIZER(struct cmd_eeprom_list_result, action, + str_eeprom_list_list); + +const char PROGMEM help_eeprom_list[] = "list all eeprom init commands"; +const parse_inst_t PROGMEM cmd_eeprom_list = { + .f = cmd_eeprom_list_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_eeprom_list, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_eeprom_list_cmd, + (PGM_P)&cmd_eeprom_list_action, + NULL, + }, +}; + + +/* ************* */ + +struct cmd_dump_i2c_result { + fixed_string_t cmd; +}; + +static void cmd_dump_i2c_parsed(void *parsed_result, void *data) +{ + struct i2c_ans_imuboard_status imu; + uint8_t irq_flags; + + (void)parsed_result; + (void)data; + + while (!cmdline_keypressed()) { + IRQ_LOCK(irq_flags); + memcpy(&imu, &imuboard_status, sizeof(imu)); + IRQ_UNLOCK(irq_flags); + + if (imu.flags & IMUBOARD_STATUS_GPS_OK) { + printf_P(PSTR("GPS lat=%"PRIi32" long=%"PRIi32 + " alt=%"PRIi32"\n"), + imu.latitude, imu.longitude, imu.altitude); + } + else + printf_P(PSTR("GPS unavailable\n")); + i2c_protocol_debug(); + wait_ms(100); + } +} + +const char PROGMEM str_dump_i2c[] = "dump_i2c"; +const parse_token_string_t PROGMEM cmd_dump_i2c_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_dump_i2c_result, cmd, + str_dump_i2c); + +const char PROGMEM help_dump_i2c[] = "dump_i2c"; +const parse_inst_t PROGMEM cmd_dump_i2c = { + .f = cmd_dump_i2c_parsed, /* function to call */ + .data = NULL, /* 2nd arg of func */ + .help_str = help_dump_i2c, + .tokens = { /* token list, NULL terminated */ + (PGM_P)&cmd_dump_i2c_cmd, + NULL, + }, +}; + + +/* ************* */ /* in progmem */ -parse_pgm_ctx_t main_ctx[] = { +const parse_ctx_t PROGMEM main_ctx[] = { /* commands_gen.c */ - (parse_pgm_inst_t *)&cmd_reset, - (parse_pgm_inst_t *)&cmd_bootloader, - (parse_pgm_inst_t *)&cmd_log, - (parse_pgm_inst_t *)&cmd_log_show, - (parse_pgm_inst_t *)&cmd_log_type, - (parse_pgm_inst_t *)&cmd_stack_space, - (parse_pgm_inst_t *)&cmd_scheduler, - (parse_pgm_inst_t *)&cmd_help, - (parse_pgm_inst_t *)&cmd_neigh_del, - (parse_pgm_inst_t *)&cmd_neigh_add, - (parse_pgm_inst_t *)&cmd_neigh_list, - (parse_pgm_inst_t *)&cmd_read, - (parse_pgm_inst_t *)&cmd_write_none, - (parse_pgm_inst_t *)&cmd_write_u8, - (parse_pgm_inst_t *)&cmd_write_u16, - (parse_pgm_inst_t *)&cmd_write_u32, - (parse_pgm_inst_t *)&cmd_sendmsg, - (parse_pgm_inst_t *)&cmd_sendmsg_name, - (parse_pgm_inst_t *)&cmd_range, - (parse_pgm_inst_t *)&cmd_range_period, - (parse_pgm_inst_t *)&cmd_range_count, - (parse_pgm_inst_t *)&cmd_range_powermask, - (parse_pgm_inst_t *)&cmd_range_dstaddr, - (parse_pgm_inst_t *)&cmd_monitor, - (parse_pgm_inst_t *)&cmd_monitor_period, - (parse_pgm_inst_t *)&cmd_monitor_add, - (parse_pgm_inst_t *)&cmd_monitor_del, - (parse_pgm_inst_t *)&cmd_ping, - (parse_pgm_inst_t *)&cmd_raw, - (parse_pgm_inst_t *)&cmd_dump, - (parse_pgm_inst_t *)&cmd_debug, -#ifndef USE_USB - (parse_pgm_inst_t *)&cmd_baudrate, -#endif + &cmd_reset, + &cmd_bootloader, + &cmd_log, + &cmd_log_show, + &cmd_log_type, + &cmd_stack_space, + &cmd_callout, + &cmd_help, + &cmd_neigh_del, + &cmd_neigh_add, + &cmd_neigh_list, + &cmd_read, + &cmd_write_none, + &cmd_write_u8, + &cmd_write_u16, + &cmd_write_u32, + &cmd_sendmsg, + &cmd_sendmsg_name, + &cmd_range, + &cmd_range_period, + &cmd_range_count, + &cmd_range_powermask, + &cmd_range_dstaddr, + &cmd_monitor, + &cmd_monitor_period, + &cmd_monitor_add, + &cmd_monitor_del, + &cmd_ping, + &cmd_raw, + &cmd_baudrate, + &cmd_beep, + &cmd_servo_set, + &cmd_servo_bypassppm, + &cmd_servo_show, + &cmd_test_spi, + &cmd_dump_xbee_stats, + &cmd_rc_proto_stats, + &cmd_rc_proto_timers, + &cmd_rc_proto_timers_show, + &cmd_rc_proto_mode, + &cmd_rc_proto_mode2, + &cmd_rc_proto_mode3, + &cmd_rc_proto_hello, + &cmd_rc_proto_hello_name, + &cmd_rc_proto_echo, + &cmd_rc_proto_echo_name, + &cmd_test_eeprom_config, + &cmd_eeprom_del, + &cmd_eeprom_add, + &cmd_eeprom_add2, + &cmd_eeprom_list, + &cmd_dump_i2c, NULL, };