allow to dump GPS info
[protos/xbee-avr.git] / commands.c
1 /*
2  *  Copyright Droids Corporation (2011)
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  *  Revision : $Id: commands.c,v 1.9 2009-11-08 17:24:33 zer0 Exp $
19  *
20  *  Olivier MATZ <zer0@droids-corp.org>
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <inttypes.h>
27 #include <aversive.h>
28 #include <aversive/pgmspace.h>
29 #include <aversive/queue.h>
30 #include <aversive/endian.h>
31 #include <aversive/error.h>
32 #include <aversive/wait.h>
33 #include <parse.h>
34 #include <rdline.h>
35 #include <parse_string.h>
36 #include <parse_num.h>
37 #include <uart.h>
38 #include <xbee.h>
39 #include <callout.h>
40
41 #include "parse_atcmd.h"
42 #include "parse_neighbor.h"
43 #include "parse_monitor.h"
44
45 #include "spi_servo.h"
46 #include "rc_proto.h"
47 #include "xbee_user.h"
48 #include "main.h"
49 #include "cmdline.h"
50 #include "beep.h"
51 #include "../fpv-common/i2c_commands.h"
52 #include "i2c_protocol.h"
53 #include "eeprom_config.h"
54
55 /* commands_gen.c */
56 extern const parse_inst_t PROGMEM cmd_reset;
57 extern const parse_inst_t PROGMEM cmd_bootloader;
58 extern const parse_inst_t PROGMEM cmd_log;
59 extern const parse_inst_t PROGMEM cmd_log_show;
60 extern const parse_inst_t PROGMEM cmd_log_type;
61 extern const parse_inst_t PROGMEM cmd_stack_space;
62 extern const parse_inst_t PROGMEM cmd_callout;
63
64 static int monitor_period_ms = 1000;
65 static int monitor_running = 0;
66 static int monitor_count = 0;
67 static struct callout monitor_event;
68 struct monitor_reg *monitor_current;
69
70 static int range_period_ms = 1000;
71 static int range_powermask = 0x1F;
72 static uint8_t range_power = 0;
73 static int range_running = 0;
74 static uint64_t range_dstaddr = 0xFFFF; /* broadcast by default */
75 static struct callout range_event;
76 static int range_count = 100;
77 static int range_cur_count = 0;
78
79 static void monitor_cb(struct callout_mgr *cm,
80                        struct callout *clt, void *dummy)
81 {
82         (void)clt;
83         (void)dummy;
84
85         if (monitor_current == NULL)
86                 monitor_current = LIST_FIRST(&xbee_monitor_list);
87
88         /* no rx_cb given: the user must check the monitored values in logs */
89         xbeeapp_send_atcmd(monitor_current->atcmd, NULL, 0, NULL, NULL);
90         monitor_current = LIST_NEXT(monitor_current, next);
91         callout_reschedule(cm, clt, monitor_period_ms / monitor_count);
92 }
93
94 static void range_cb(struct callout_mgr *cm,
95                      struct callout *clt, void *dummy)
96 {
97         struct rc_proto_power_probe power_probe;
98         struct xbee_msg msg;
99         uint8_t i, mask;
100
101         (void)clt;
102         (void)dummy;
103
104         range_cur_count--;
105
106         /* get new xmit power */
107         for (i = 1; i <= 8; i++) {
108                 mask = 1 << ((range_power + i) & 0x7);
109                 if (mask & range_powermask)
110                         break;
111         }
112         range_power = ((range_power + i) & 0x7);
113
114         xbeeapp_send_atcmd("PL", &range_power, sizeof(range_power), NULL, NULL);
115
116         power_probe.type = RC_PROTO_POWER_PROBE;
117         power_probe.power_level = range_power;
118
119         msg.iovlen = 1;
120         msg.iov[0].buf = &power_probe;
121         msg.iov[0].len = sizeof(power_probe);
122
123         xbeeapp_send_msg(range_dstaddr, &msg, NULL, NULL);
124
125         if (range_cur_count == 0) {
126                 range_running = 0;
127                 callout_stop(cm, clt);
128                 return;
129         }
130
131         callout_reschedule(cm, clt, range_period_ms);
132 }
133
134 /* callback invoked when a xbee_send is done */
135 static int8_t send_msg_cb(int8_t retcode, void *frame, unsigned len,
136         void *arg)
137 {
138         struct xbee_xmit_status_hdr *recvframe = frame;
139         uint8_t *done = arg;
140
141         *done = 1;
142         if (retcode == XBEE_USER_RETCODE_TIMEOUT) {
143                 printf_P(PSTR("timeout\r\n"));
144                 return retcode;
145         }
146         if (retcode == XBEE_USER_RETCODE_BAD_FRAME ||
147                 len != sizeof(*recvframe)) {
148                 printf_P(PSTR("invalid frame\r\n"));
149                 return XBEE_USER_RETCODE_BAD_FRAME;
150         }
151
152         printf_P(PSTR("ok\r\n"));
153         return XBEE_USER_RETCODE_OK;
154 }
155
156 /* callback invoked to dump the response to AT command */
157 static int8_t dump_xbee_atresp_cb(int8_t retcode, void *frame, unsigned len,
158         void *arg)
159 {
160         struct xbee_atresp_hdr *recvframe = frame;
161         char atcmd_str[3];
162         char buf[32];
163         uint8_t *done = arg;
164
165         *done = 1;
166         if (retcode == XBEE_USER_RETCODE_TIMEOUT) {
167                 printf_P(PSTR("timeout\r\n"));
168                 return retcode;
169         }
170         if (retcode == XBEE_USER_RETCODE_BAD_FRAME ||
171                 len <  sizeof(*recvframe)) {
172                 printf_P(PSTR("invalid frame\r\n"));
173                 return XBEE_USER_RETCODE_BAD_FRAME;
174         }
175
176         /* get AT command from frame */
177         memcpy(atcmd_str, &recvframe->cmd, 2);
178         atcmd_str[2] = '\0';
179
180         atresp_to_str(buf, sizeof(buf), frame, len);
181         len -= sizeof(*recvframe);
182         printf_P(PSTR("status ok, len=%d, %s\n"), len, buf);
183         return XBEE_USER_RETCODE_OK;
184 }
185
186 /* this structure is filled when cmd_help is parsed successfully */
187 struct cmd_help_result {
188         fixed_string_t help;
189         struct xbee_atcmd *cmd;
190 };
191
192 /* function called when cmd_help is parsed successfully */
193 static void cmd_help_parsed(void *parsed_result, void *data)
194 {
195         struct cmd_help_result *res = parsed_result;
196         struct xbee_atcmd cmdcopy;
197         int type;
198
199         (void)data;
200
201         memcpy_P(&cmdcopy, res->cmd, sizeof(cmdcopy));
202         type = (cmdcopy.flags & (XBEE_ATCMD_F_READ | XBEE_ATCMD_F_WRITE));
203         switch (type) {
204                 case XBEE_ATCMD_F_READ:
205                         printf_P(PSTR("Read-only\r\n"));
206                         break;
207                 case XBEE_ATCMD_F_WRITE:
208                         printf_P(PSTR("Write-only\r\n"));
209                         break;
210                 default:
211                         printf_P(PSTR("Read-write\r\n"));
212                         break;
213         }
214         if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_NONE)
215                 printf_P(PSTR("No argument\r\n"));
216         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_U8)
217                 printf_P(PSTR("Register is unsigned 8 bits\r\n"));
218         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_U16)
219                 printf_P(PSTR("Register is unsigned 16 bits\r\n"));
220         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_U32)
221                 printf_P(PSTR("Register is unsigned 32 bits\r\n"));
222         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_S16)
223                 printf_P(PSTR("Register is signed 16 bits\r\n"));
224         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_STRING_20B)
225                 printf_P(PSTR("Register is a 20 bytes string\r\n"));
226         else
227                 printf_P(PSTR("Unknown argument\r\n"));
228
229         printf_P(PSTR("%S\r\n"), cmdcopy.help);
230 }
231 const char PROGMEM str_help_help[] = "help";
232
233 const parse_token_string_t PROGMEM cmd_help_help =
234         TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, str_help_help);
235
236 const parse_token_atcmd_t PROGMEM cmd_help_atcmd =
237         TOKEN_ATCMD_INITIALIZER(struct cmd_help_result, cmd, &xbee_dev,
238                                 0, 0);
239
240 const char PROGMEM help_help[] = "Help a register using an AT command";
241 const parse_inst_t PROGMEM cmd_help = {
242         .f = cmd_help_parsed,  /* function to call */
243         .data = NULL,      /* 2nd arg of func */
244         .help_str = help_help,
245         .tokens = {        /* token list, NULL terminated */
246                 (PGM_P)&cmd_help_help,
247                 (PGM_P)&cmd_help_atcmd,
248                 NULL,
249         },
250 };
251
252 /* ************* */
253
254 struct cmd_neigh_del_result {
255         fixed_string_t cmd;
256         fixed_string_t action;
257         struct xbee_neigh *neigh;
258 };
259
260 static void cmd_neigh_del_parsed(void *parsed_result,
261                                 void *data)
262 {
263         struct cmd_neigh_del_result *res = parsed_result;
264
265         (void)data;
266         xbee_neigh_del(xbee_dev, res->neigh);
267 }
268
269 const char PROGMEM str_neigh_del_neigh[] = "neigh";
270 const parse_token_string_t PROGMEM cmd_neigh_del_cmd =
271         TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, cmd,
272                                  str_neigh_del_neigh);
273 const char PROGMEM str_neigh_del_del[] = "del";
274 const parse_token_string_t PROGMEM cmd_neigh_del_action =
275         TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, action,
276                                  str_neigh_del_del);
277 const parse_token_neighbor_t PROGMEM cmd_neigh_del_neigh =
278         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_neigh_del_result, neigh,
279                                    &xbee_dev);
280
281 const char PROGMEM help_neigh_del[] = "delete a neighbor";
282 const parse_inst_t PROGMEM cmd_neigh_del = {
283         .f = cmd_neigh_del_parsed,  /* function to call */
284         .data = NULL,      /* 2nd arg of func */
285         .help_str = help_neigh_del,
286         .tokens = {        /* token list, NULL terminated */
287                 (PGM_P)&cmd_neigh_del_cmd,
288                 (PGM_P)&cmd_neigh_del_action,
289                 (PGM_P)&cmd_neigh_del_neigh,
290                 NULL,
291         },
292 };
293
294 /* ************* */
295
296 struct cmd_neigh_add_result {
297         fixed_string_t cmd;
298         fixed_string_t action;
299         fixed_string_t name;
300         uint64_t addr;
301 };
302
303 static void cmd_neigh_add_parsed(void *parsed_result,
304                                  void *data)
305 {
306         struct cmd_neigh_add_result *res = parsed_result;
307
308         (void)data;
309         if (xbee_neigh_add(xbee_dev, res->name, res->addr) == NULL)
310                 printf_P(PSTR("name or addr already exist\r\n"));
311 }
312
313 const char PROGMEM str_neigh_add_neigh[] = "neigh";
314 const parse_token_string_t PROGMEM cmd_neigh_add_cmd =
315         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, cmd,
316                                  str_neigh_add_neigh);
317 const char PROGMEM str_neigh_add_add[] = "add";
318 const parse_token_string_t PROGMEM cmd_neigh_add_action =
319         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, action,
320                                  str_neigh_add_add);
321 const parse_token_string_t PROGMEM cmd_neigh_add_name =
322         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, name, NULL);
323 const parse_token_num_t PROGMEM cmd_neigh_add_addr =
324         TOKEN_NUM_INITIALIZER(struct cmd_neigh_add_result, addr, UINT64);
325
326 const char PROGMEM help_neigh_add[] = "add a neighbor";
327 const parse_inst_t PROGMEM cmd_neigh_add = {
328         .f = cmd_neigh_add_parsed,  /* function to call */
329         .data = NULL,      /* 2nd arg of func */
330         .help_str = help_neigh_add,
331         .tokens = {        /* token list, NULL terminated */
332                 (PGM_P)&cmd_neigh_add_cmd,
333                 (PGM_P)&cmd_neigh_add_action,
334                 (PGM_P)&cmd_neigh_add_name,
335                 (PGM_P)&cmd_neigh_add_addr,
336                 NULL,
337         },
338 };
339
340 /* ************* */
341
342 struct cmd_neigh_list_result {
343         fixed_string_t cmd;
344         fixed_string_t action;
345 };
346
347 static void cmd_neigh_list_parsed(void *parsed_result,
348                                 void *data)
349 {
350         struct xbee_neigh *neigh;
351
352         (void)parsed_result;
353         (void)data;
354         LIST_FOREACH(neigh, &xbee_dev->neigh_list, next) {
355                 printf_P(PSTR(" %s: 0x%.8"PRIx32"%.8"PRIx32"\r\n"),
356                          neigh->name,
357                          (uint32_t)(neigh->addr >> 32ULL),
358                          (uint32_t)(neigh->addr & 0xFFFFFFFF));
359         }
360 }
361
362 const char PROGMEM str_neigh_list_neigh[] = "neigh";
363 const parse_token_string_t PROGMEM cmd_neigh_list_cmd =
364         TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, cmd,
365                                  str_neigh_list_neigh);
366 const char PROGMEM str_neigh_list_list[] = "list";
367 const parse_token_string_t PROGMEM cmd_neigh_list_action =
368         TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, action,
369                                  str_neigh_list_list);
370
371 const char PROGMEM help_neigh_list[] = "list all knwon neighbors";
372 const parse_inst_t PROGMEM cmd_neigh_list = {
373         .f = cmd_neigh_list_parsed,  /* function to call */
374         .data = NULL,      /* 2nd arg of func */
375         .help_str = help_neigh_list,
376         .tokens = {        /* token list, NULL terminated */
377                 (PGM_P)&cmd_neigh_list_cmd,
378                 (PGM_P)&cmd_neigh_list_action,
379                 NULL,
380         },
381 };
382
383 /* ************* */
384
385 /* this structure is filled when cmd_read is parsed successfully */
386 struct cmd_read_result {
387         fixed_string_t read;
388         struct xbee_atcmd *cmd;
389 };
390
391 /* function called when cmd_read is parsed successfully */
392 static void cmd_read_parsed(void *parsed_result,
393                             void *data)
394 {
395         struct cmd_read_result *res = parsed_result;
396         struct xbee_atcmd copy;
397         char cmd[3];
398         volatile uint8_t done = 0;
399
400         (void)data;
401         memcpy_P(&copy, res->cmd, sizeof(copy));
402         memcpy_P(&cmd, copy.name, 2);
403         cmd[2] = '\0';
404         xbeeapp_send_atcmd(cmd, NULL, 0, dump_xbee_atresp_cb, (void *)&done);
405         while (done == 0);
406 }
407
408 const char PROGMEM str_read_read[] = "read";
409
410 const parse_token_string_t PROGMEM cmd_read_read =
411         TOKEN_STRING_INITIALIZER(struct cmd_read_result, read,
412                                  str_read_read);
413
414 const parse_token_atcmd_t PROGMEM cmd_read_atcmd =
415         TOKEN_ATCMD_INITIALIZER(struct cmd_read_result, cmd, &xbee_dev,
416                                 XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ);
417
418 const char PROGMEM help_read[] = "Read a register using an AT command";
419 const parse_inst_t PROGMEM cmd_read = {
420         .f = cmd_read_parsed,  /* function to call */
421         .data = NULL,      /* 2nd arg of func */
422         .help_str = help_read,
423         .tokens = {        /* token list, NULL terminated */
424                 (PGM_P)&cmd_read_read,
425                 (PGM_P)&cmd_read_atcmd,
426                 NULL,
427         },
428 };
429
430
431 /* ************* */
432
433 /* this structure is filled when cmd_write is parsed successfully */
434 struct cmd_write_result {
435         fixed_string_t write;
436         struct xbee_atcmd *cmd;
437         union {
438                 uint8_t u8;
439                 uint16_t u16;
440                 uint32_t u32;
441         };
442 };
443
444 /* function called when cmd_write is parsed successfully */
445 static void cmd_write_parsed(void *parsed_result, void *data)
446 {
447         struct cmd_write_result *res = parsed_result;
448         struct xbee_atcmd copy;
449         char cmd[3];
450         int len;
451         void *param;
452         volatile uint8_t done = 0;
453
454         (void)data;
455         memcpy_P(&copy, res->cmd, sizeof(copy));
456
457         if (copy.flags & XBEE_ATCMD_F_PARAM_NONE) {
458                 len = 0;
459                 param = NULL;
460         }
461         else if (copy.flags & XBEE_ATCMD_F_PARAM_U8) {
462                 len = sizeof(res->u8);
463                 param = &res->u8;
464         }
465         else if (copy.flags & XBEE_ATCMD_F_PARAM_U16) {
466                 len = sizeof(res->u16);
467                 res->u16 = htons(res->u16);
468                 param = &res->u16;
469         }
470         else if (copy.flags & XBEE_ATCMD_F_PARAM_U32) {
471                 len = sizeof(res->u32);
472                 res->u32 = htonl(res->u32);
473                 param = &res->u32;
474         }
475         else {
476                 printf_P(PSTR("Unknown argument type\r\n"));
477                 return;
478         }
479         memcpy_P(&cmd, copy.name, 2);
480         cmd[2] = '\0';
481         xbeeapp_send_atcmd(cmd, param, len, dump_xbee_atresp_cb, (void *)&done);
482         while (done == 0);
483 }
484
485 const char PROGMEM str_write_none[] = "write";
486
487 const parse_token_string_t PROGMEM cmd_write_write =
488         TOKEN_STRING_INITIALIZER(struct cmd_write_result, write,
489                                  str_write_none);
490
491 const parse_token_atcmd_t PROGMEM cmd_write_none_atcmd =
492         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
493                                 &xbee_dev,
494                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE,
495                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE);
496
497 const char PROGMEM help_write_none[] = "Send an AT command (no argument)";
498
499 const parse_inst_t PROGMEM cmd_write_none = {
500         .f = cmd_write_parsed,  /* function to call */
501         .data = NULL,      /* 2nd arg of func */
502         .help_str = help_write_none,
503         .tokens = {        /* token list, NULL terminated */
504                 (PGM_P)&cmd_write_write,
505                 (PGM_P)&cmd_write_none_atcmd,
506                 NULL,
507         },
508 };
509
510 const parse_token_atcmd_t PROGMEM cmd_write_u8_atcmd =
511         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
512                                 &xbee_dev,
513                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8,
514                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8);
515
516 const parse_token_num_t PROGMEM cmd_write_u8_u8 =
517         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u8, UINT8);
518
519 const char PROGMEM help_write_u8[] = "Write a 8 bits register using an AT command";
520
521 const parse_inst_t PROGMEM cmd_write_u8 = {
522         .f = cmd_write_parsed,  /* function to call */
523         .data = NULL,      /* 2nd arg of func */
524         .help_str = help_write_u8,
525         .tokens = {        /* token list, NULL terminated */
526                 (PGM_P)&cmd_write_write,
527                 (PGM_P)&cmd_write_u8_atcmd,
528                 (PGM_P)&cmd_write_u8_u8,
529                 NULL,
530         },
531 };
532
533 const parse_token_atcmd_t PROGMEM cmd_write_u16_atcmd =
534         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
535                                 &xbee_dev,
536                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16,
537                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16);
538
539 const parse_token_num_t PROGMEM cmd_write_u16_u16 =
540         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u16, UINT16);
541
542 const char PROGMEM help_write_u16[] = "Write a 16 bits register using an AT command";
543
544 const parse_inst_t PROGMEM cmd_write_u16 = {
545         .f = cmd_write_parsed,  /* function to call */
546         .data = NULL,      /* 2nd arg of func */
547         .help_str = help_write_u16,
548         .tokens = {        /* token list, NULL terminated */
549                 (PGM_P)&cmd_write_write,
550                 (PGM_P)&cmd_write_u16_atcmd,
551                 (PGM_P)&cmd_write_u16_u16,
552                 NULL,
553         },
554 };
555
556 const parse_token_atcmd_t PROGMEM cmd_write_u32_atcmd =
557         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
558                                 &xbee_dev,
559                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32,
560                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32);
561
562 const parse_token_num_t PROGMEM cmd_write_u32_u32 =
563         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u32, UINT32);
564
565 const char PROGMEM help_write_u32[] = "Write a 32 bits register using an AT command";
566
567 const parse_inst_t PROGMEM cmd_write_u32 = {
568         .f = cmd_write_parsed,  /* function to call */
569         .data = NULL,      /* 2nd arg of func */
570         .help_str = help_write_u32,
571         .tokens = {        /* token list, NULL terminated */
572                 (PGM_P)&cmd_write_write,
573                 (PGM_P)&cmd_write_u32_atcmd,
574                 (PGM_P)&cmd_write_u32_u32,
575                 NULL,
576         },
577 };
578
579
580 /* ************* */
581
582 /* this structure is filled when cmd_sendmsg is parsed successfully */
583 struct cmd_sendmsg_result {
584         fixed_string_t sendmsg;
585         uint64_t addr;
586         fixed_string_t data;
587 };
588
589 /* function called when cmd_sendmsg is parsed successfully */
590 static void cmd_sendmsg_parsed(void *parsed_result, void *data)
591 {
592         struct cmd_sendmsg_result *res = parsed_result;
593         struct xbee_msg msg;
594         volatile uint8_t done = 0;
595
596         (void)data;
597
598         msg.iovlen = 1;
599         msg.iov[0].buf = res->data;
600         msg.iov[0].len = strlen(res->data);
601
602         xbeeapp_send_msg(res->addr, &msg, send_msg_cb, (void *)&done);
603         while (done == 0);
604 }
605
606 const char PROGMEM str_sendmsg[] = "sendmsg";
607
608 const parse_token_string_t PROGMEM cmd_sendmsg_sendmsg =
609         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, sendmsg,
610                                  str_sendmsg);
611
612 const parse_token_num_t PROGMEM cmd_sendmsg_addr =
613         TOKEN_NUM_INITIALIZER(struct cmd_sendmsg_result, addr, UINT64);
614
615 const parse_token_string_t PROGMEM cmd_sendmsg_data =
616         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, data, NULL);
617
618 const char PROGMEM help_sendmsg[] = "Send data to a node using its address";
619
620 const parse_inst_t PROGMEM cmd_sendmsg = {
621         .f = cmd_sendmsg_parsed,  /* function to call */
622         .data = NULL,      /* 2nd arg of func */
623         .help_str = help_sendmsg,
624         .tokens = {        /* token list, NULL terminated */
625                 (PGM_P)&cmd_sendmsg_sendmsg,
626                 (PGM_P)&cmd_sendmsg_addr,
627                 (PGM_P)&cmd_sendmsg_data,
628                 NULL,
629         },
630 };
631
632 /* ************* */
633
634 /* this structure is filled when cmd_sendmsg_name is parsed successfully */
635 struct cmd_sendmsg_name_result {
636         fixed_string_t sendmsg_name;
637         struct xbee_neigh *neigh;
638         fixed_string_t data;
639 };
640
641 /* function called when cmd_sendmsg_name is parsed successfully */
642 static void cmd_sendmsg_name_parsed(void *parsed_result, void *data)
643 {
644         struct cmd_sendmsg_name_result *res = parsed_result;
645         struct xbee_msg msg;
646         volatile uint8_t done = 0;
647
648         (void)data;
649
650         msg.iovlen = 1;
651         msg.iov[0].buf = res->data;
652         msg.iov[0].len = strlen(res->data);
653
654         xbeeapp_send_msg(res->neigh->addr, &msg, send_msg_cb, (void *)&done);
655         while (done == 0);
656 }
657
658 const parse_token_string_t PROGMEM cmd_sendmsg_name_sendmsg_name =
659         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, sendmsg_name,
660                                  str_sendmsg);
661
662 const parse_token_neighbor_t PROGMEM cmd_sendmsg_name_neigh =
663         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_sendmsg_name_result, neigh,
664                                    &xbee_dev);
665
666 const parse_token_string_t PROGMEM cmd_sendmsg_name_data =
667         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, data, NULL);
668
669 const char PROGMEM help_sendmsg_name[] = "Send data to a node using its name";
670
671 const parse_inst_t PROGMEM cmd_sendmsg_name = {
672         .f = cmd_sendmsg_name_parsed,  /* function to call */
673         .data = NULL,      /* 2nd arg of func */
674         .help_str = help_sendmsg_name,
675         .tokens = {        /* token list, NULL terminated */
676                 (PGM_P)&cmd_sendmsg_name_sendmsg_name,
677                 (PGM_P)&cmd_sendmsg_name_neigh,
678                 (PGM_P)&cmd_sendmsg_name_data,
679                 NULL,
680         },
681 };
682
683
684 /* ************* */
685
686 /* this structure is filled when cmd_range is parsed successfully */
687 struct cmd_range_result {
688         fixed_string_t range;
689         fixed_string_t action;
690 };
691
692 /* function called when cmd_range is parsed successfully */
693 static void cmd_range_parsed(void *parsed_result, void *data)
694 {
695         struct cmd_range_result *res = parsed_result;
696
697         (void)data;
698         if (!strcmp_P(res->action, PSTR("show"))) {
699                 printf_P(PSTR("range infos:\r\n"));
700                 printf_P(PSTR("  range period %d\r\n"), range_period_ms);
701                 printf_P(PSTR("  range count %d\r\n"), range_count);
702                 printf_P(PSTR("  range powermask 0x%x\r\n"), range_powermask);
703                 printf_P(PSTR("  range dstaddr 0x%.8"PRIx32"%.8"PRIx32"\r\n"),
704                          (uint32_t)(range_dstaddr >> 32ULL),
705                          (uint32_t)(range_dstaddr & 0xFFFFFFFF));
706
707                 if (range_running)
708                         printf_P(PSTR("  range test is running\r\n"));
709                 else
710                         printf_P(PSTR("  range test is not running\r\n"));
711         }
712         else if (!strcmp(res->action, "start")) {
713                 if (range_running) {
714                         printf_P(PSTR("already running\r\n"));
715                         return;
716                 }
717                 range_cur_count = range_count;
718                 callout_init(&range_event, range_cb, NULL, LOW_PRIO);
719                 range_running = 1;
720                 callout_schedule(&xbeeboard.intr_cm,
721                         &range_event, 0); /* immediate */
722         }
723         else if (!strcmp(res->action, "end")) {
724                 if (range_running == 0) {
725                         printf_P(PSTR("not running\r\n"));
726                         return;
727                 }
728                 callout_stop(&xbeeboard.intr_cm, &range_event);
729                 range_running = 0;
730         }
731 }
732
733 const char PROGMEM str_range[] = "range";
734 const char PROGMEM str_range_tokens[] = "show#start#end";
735
736 const parse_token_string_t PROGMEM cmd_range_range =
737         TOKEN_STRING_INITIALIZER(struct cmd_range_result, range,
738                                  str_range);
739 const parse_token_string_t PROGMEM cmd_range_action =
740         TOKEN_STRING_INITIALIZER(struct cmd_range_result, action,
741                                  str_range_tokens);
742
743 const char PROGMEM help_range[] = "start/stop/show current rangeing";
744
745 const parse_inst_t PROGMEM cmd_range = {
746         .f = cmd_range_parsed,  /* function to call */
747         .data = NULL,      /* 2nd arg of func */
748         .help_str = help_range,
749         .tokens = {        /* token list, NULL terminated */
750                 (PGM_P)&cmd_range_range,
751                 (PGM_P)&cmd_range_action,
752                 NULL,
753         },
754 };
755
756 /* ************* */
757
758 /* this structure is filled when cmd_range_period is parsed successfully */
759 struct cmd_range_period_result {
760         fixed_string_t range;
761         fixed_string_t action;
762         uint32_t period;
763 };
764
765 /* function called when cmd_range_period is parsed successfully */
766 static void cmd_range_period_parsed(void *parsed_result, void *data)
767 {
768         struct cmd_range_period_result *res = parsed_result;
769
770         (void)data;
771         if (res->period < 10) {
772                 printf_P(PSTR("error, minimum period is 10 ms\r\n"));
773                 return;
774         }
775
776         range_period_ms = res->period;
777 }
778
779 const char PROGMEM str_period[] = "period";
780
781 const parse_token_string_t PROGMEM cmd_range_period_range_period =
782         TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, range,
783                                  str_range);
784 const parse_token_string_t PROGMEM cmd_range_period_action =
785         TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, action,
786                                  str_period);
787 const parse_token_num_t PROGMEM cmd_range_period_period =
788         TOKEN_NUM_INITIALIZER(struct cmd_range_period_result, period, UINT32);
789
790 const char PROGMEM help_range_period[] = "set range test period";
791
792 const parse_inst_t PROGMEM cmd_range_period = {
793         .f = cmd_range_period_parsed,  /* function to call */
794         .data = NULL,      /* 2nd arg of func */
795         .help_str = help_range_period,
796         .tokens = {        /* token list, NULL terminated */
797                 (PGM_P)&cmd_range_period_range_period,
798                 (PGM_P)&cmd_range_period_action,
799                 (PGM_P)&cmd_range_period_period,
800                 NULL,
801         },
802 };
803
804 /* ************* */
805
806 /* this structure is filled when cmd_range_count is parsed successfully */
807 struct cmd_range_count_result {
808         fixed_string_t range;
809         fixed_string_t action;
810         uint32_t count;
811 };
812
813 /* function called when cmd_range_count is parsed successfully */
814 static void cmd_range_count_parsed(void *parsed_result, void *data)
815 {
816         struct cmd_range_count_result *res = parsed_result;
817
818         (void)data;
819         range_count = res->count;
820 }
821
822 const char PROGMEM str_count[] = "count";
823
824 const parse_token_string_t PROGMEM cmd_range_count_range_count =
825         TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, range,
826                                  str_range);
827 const parse_token_string_t PROGMEM cmd_range_count_action =
828         TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, action,
829                                  str_count);
830 const parse_token_num_t PROGMEM cmd_range_count_count =
831         TOKEN_NUM_INITIALIZER(struct cmd_range_count_result, count, UINT32);
832
833
834 const char PROGMEM help_range_count[] = "set range test count";
835
836 const parse_inst_t PROGMEM cmd_range_count = {
837         .f = cmd_range_count_parsed,  /* function to call */
838         .data = NULL,      /* 2nd arg of func */
839         .help_str = help_range_count,
840         .tokens = {        /* token list, NULL terminated */
841                 (PGM_P)&cmd_range_count_range_count,
842                 (PGM_P)&cmd_range_count_action,
843                 (PGM_P)&cmd_range_count_count,
844                 NULL,
845         },
846 };
847
848 /* ************* */
849
850 /* this structure is filled when cmd_range_powermask is parsed successfully */
851 struct cmd_range_powermask_result {
852         fixed_string_t range;
853         fixed_string_t action;
854         uint8_t powermask;
855 };
856
857 /* function called when cmd_range_powermask is parsed successfully */
858 static void cmd_range_powermask_parsed(void *parsed_result, void *data)
859 {
860         struct cmd_range_powermask_result *res = parsed_result;
861
862         (void)data;
863         range_powermask = res->powermask;
864 }
865
866 const char PROGMEM str_powermask[] = "powermask";
867
868 const parse_token_string_t PROGMEM cmd_range_powermask_range_powermask =
869         TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, range,
870                                  str_range);
871 const parse_token_string_t PROGMEM cmd_range_powermask_action =
872         TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, action,
873                                  str_powermask);
874 const parse_token_num_t PROGMEM cmd_range_powermask_powermask =
875         TOKEN_NUM_INITIALIZER(struct cmd_range_powermask_result, powermask,
876                               UINT8);
877
878
879 const char PROGMEM help_range_powermask[] = "set range test powermask";
880
881 const parse_inst_t PROGMEM cmd_range_powermask = {
882         .f = cmd_range_powermask_parsed,  /* function to call */
883         .data = NULL,      /* 2nd arg of func */
884         .help_str = help_range_powermask,
885         .tokens = {        /* token list, NULL terminated */
886                 (PGM_P)&cmd_range_powermask_range_powermask,
887                 (PGM_P)&cmd_range_powermask_action,
888                 (PGM_P)&cmd_range_powermask_powermask,
889                 NULL,
890         },
891 };
892
893 /* ************* */
894
895 /* this structure is filled when cmd_range_dstaddr is parsed successfully */
896 struct cmd_range_dstaddr_result {
897         fixed_string_t range;
898         fixed_string_t action;
899         uint64_t dstaddr;
900 };
901
902 /* function called when cmd_range_dstaddr is parsed successfully */
903 static void cmd_range_dstaddr_parsed(void *parsed_result, void *data)
904 {
905         struct cmd_range_dstaddr_result *res = parsed_result;
906
907         (void)data;
908         range_dstaddr = res->dstaddr;
909 }
910
911 const char PROGMEM str_dstaddr[] = "dstaddr";
912
913 const parse_token_string_t PROGMEM cmd_range_dstaddr_range_dstaddr =
914         TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, range,
915                                  str_range);
916 const parse_token_string_t PROGMEM cmd_range_dstaddr_action =
917         TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, action,
918                                  str_dstaddr);
919 const parse_token_num_t PROGMEM cmd_range_dstaddr_dstaddr =
920         TOKEN_NUM_INITIALIZER(struct cmd_range_dstaddr_result, dstaddr, UINT64);
921
922
923 const char PROGMEM help_range_dstaddr[] = "set register rangeing dstaddr";
924
925 const parse_inst_t PROGMEM cmd_range_dstaddr = {
926         .f = cmd_range_dstaddr_parsed,  /* function to call */
927         .data = NULL,      /* 2nd arg of func */
928         .help_str = help_range_dstaddr,
929         .tokens = {        /* token list, NULL terminated */
930                 (PGM_P)&cmd_range_dstaddr_range_dstaddr,
931                 (PGM_P)&cmd_range_dstaddr_action,
932                 (PGM_P)&cmd_range_dstaddr_dstaddr,
933                 NULL,
934         },
935 };
936
937
938 /* ************* */
939
940 /* this structure is filled when cmd_monitor is parsed successfully */
941 struct cmd_monitor_result {
942         fixed_string_t monitor;
943         fixed_string_t action;
944 };
945
946 /* function called when cmd_monitor is parsed successfully */
947 static void cmd_monitor_parsed(void *parsed_result, void *data)
948 {
949         struct cmd_monitor_result *res = parsed_result;
950         struct monitor_reg *m;
951
952         (void)data;
953         if (!strcmp_P(res->action, PSTR("show"))) {
954                 printf_P(PSTR("monitor period is %d ms, %d regs in list\r\n"),
955                        monitor_period_ms, monitor_count);
956                 LIST_FOREACH(m, &xbee_monitor_list, next)
957                         printf_P(PSTR(" %S\r\n"), m->desc);
958         }
959         else if (!strcmp_P(res->action, PSTR("start"))) {
960                 if (monitor_running) {
961                         printf_P(PSTR("already running\r\n"));
962                         return;
963                 }
964                 if (monitor_count == 0) {
965                         printf_P(PSTR("no regs to be monitored\r\n"));
966                         return;
967                 }
968                 callout_init(&monitor_event, monitor_cb, NULL, 1);
969                 monitor_running = 1;
970                 monitor_current = LIST_FIRST(&xbee_monitor_list);
971                 callout_schedule(&xbeeboard.intr_cm,
972                         &monitor_event, 0); /* immediate */
973                 printf_P(PSTR("monitor cb: %S %s\r\n"),
974                          monitor_current->desc,
975                          monitor_current->atcmd);
976
977         }
978         else if (!strcmp_P(res->action, PSTR("end"))) {
979                 if (monitor_running == 0) {
980                         printf_P(PSTR("not running\r\n"));
981                         return;
982                 }
983                 callout_stop(&xbeeboard.intr_cm, &monitor_event);
984                 monitor_running = 0;
985         }
986 }
987
988 const char PROGMEM str_monitor[] = "monitor";
989 const char PROGMEM str_monitor_tokens[] = "show#start#end";
990
991 const parse_token_string_t PROGMEM cmd_monitor_monitor =
992         TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, monitor,
993                                  str_monitor);
994 const parse_token_string_t PROGMEM cmd_monitor_action =
995         TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, action,
996                                  str_monitor_tokens);
997
998 const char PROGMEM help_monitor[] = "start/stop/show current monitoring";
999
1000 const parse_inst_t PROGMEM cmd_monitor = {
1001         .f = cmd_monitor_parsed,  /* function to call */
1002         .data = NULL,      /* 2nd arg of func */
1003         .help_str = help_monitor,
1004         .tokens = {        /* token list, NULL terminated */
1005                 (PGM_P)&cmd_monitor_monitor,
1006                 (PGM_P)&cmd_monitor_action,
1007                 NULL,
1008         },
1009 };
1010
1011 /* ************* */
1012
1013 /* this structure is filled when cmd_monitor_add is parsed successfully */
1014 struct cmd_monitor_add_result {
1015         fixed_string_t monitor;
1016         fixed_string_t action;
1017         struct xbee_atcmd *cmd;
1018 };
1019
1020 /* function called when cmd_monitor_add is parsed successfully */
1021 static void cmd_monitor_add_parsed(void *parsed_result, void *data)
1022 {
1023         struct cmd_monitor_add_result *res = parsed_result;
1024         struct monitor_reg *m;
1025         struct xbee_atcmd copy;
1026
1027         (void)data;
1028         memcpy_P(&copy, res->cmd, sizeof(copy));
1029         LIST_FOREACH(m, &xbee_monitor_list, next) {
1030                 if (!strcmp_P(m->atcmd, copy.name))
1031                         break;
1032         }
1033
1034         if (m != NULL) {
1035                 printf_P(PSTR("already exist\r\n"));
1036                 return;
1037         }
1038
1039         m = malloc(sizeof(*m));
1040         if (m == NULL) {
1041                 printf_P(PSTR("no mem\r\n"));
1042                 return;
1043         }
1044         m->desc = copy.desc;
1045         strcpy_P(m->atcmd, copy.name);
1046         LIST_INSERT_HEAD(&xbee_monitor_list, m, next);
1047         monitor_count ++;
1048 }
1049
1050 const char PROGMEM str_monitor_add[] = "add";
1051
1052 const parse_token_string_t PROGMEM cmd_monitor_add_monitor_add =
1053         TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, monitor,
1054                                  str_monitor);
1055 const parse_token_string_t PROGMEM cmd_monitor_add_action =
1056         TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, action,
1057                                  str_monitor_add);
1058 const parse_token_atcmd_t PROGMEM cmd_monitor_add_atcmd =
1059         TOKEN_ATCMD_INITIALIZER(struct cmd_monitor_add_result, cmd, &xbee_dev,
1060                                 XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ);
1061
1062
1063 const char PROGMEM help_monitor_add[] = "add a register in monitor list";
1064
1065 const parse_inst_t PROGMEM cmd_monitor_add = {
1066         .f = cmd_monitor_add_parsed,  /* function to call */
1067         .data = NULL,      /* 2nd arg of func */
1068         .help_str = help_monitor_add,
1069         .tokens = {        /* token list, NULL terminated */
1070                 (PGM_P)&cmd_monitor_add_monitor_add,
1071                 (PGM_P)&cmd_monitor_add_action,
1072                 (PGM_P)&cmd_monitor_add_atcmd,
1073                 NULL,
1074         },
1075 };
1076
1077 /* ************* */
1078
1079 /* this structure is filled when cmd_monitor_period is parsed successfully */
1080 struct cmd_monitor_period_result {
1081         fixed_string_t monitor;
1082         fixed_string_t action;
1083         uint32_t period;
1084 };
1085
1086 /* function called when cmd_monitor_period is parsed successfully */
1087 static void cmd_monitor_period_parsed(void *parsed_result, void *data)
1088 {
1089         struct cmd_monitor_period_result *res = parsed_result;
1090
1091         (void)data;
1092         if (res->period < 100) {
1093                 printf_P(PSTR("error, minimum period is 100 ms\r\n"));
1094                 return;
1095         }
1096
1097         monitor_period_ms = res->period;
1098 }
1099
1100 const char PROGMEM str_monitor_period[] = "period";
1101
1102 const parse_token_string_t PROGMEM cmd_monitor_period_monitor_period =
1103         TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, monitor,
1104                                  str_monitor);
1105 const parse_token_string_t PROGMEM cmd_monitor_period_action =
1106         TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, action,
1107                                  str_monitor_period);
1108 const parse_token_num_t PROGMEM cmd_monitor_period_period =
1109         TOKEN_NUM_INITIALIZER(struct cmd_monitor_period_result, period, UINT32);
1110
1111
1112 const char PROGMEM help_monitor_period[] = "set register monitoring period";
1113
1114 const parse_inst_t PROGMEM cmd_monitor_period = {
1115         .f = cmd_monitor_period_parsed,  /* function to call */
1116         .data = NULL,      /* 2nd arg of func */
1117         .help_str = help_monitor_period,
1118         .tokens = {        /* token list, NULL terminated */
1119                 (PGM_P)&cmd_monitor_period_monitor_period,
1120                 (PGM_P)&cmd_monitor_period_action,
1121                 (PGM_P)&cmd_monitor_period_period,
1122                 NULL,
1123         },
1124 };
1125
1126 /* ************* */
1127
1128 /* this structure is filled when cmd_monitor_del is parsed successfully */
1129 struct cmd_monitor_del_result {
1130         fixed_string_t monitor;
1131         fixed_string_t action;
1132         struct monitor_reg *m;
1133 };
1134
1135 /* function called when cmd_monitor_del is parsed successfully */
1136 static void cmd_monitor_del_parsed(void *parsed_result, void *data)
1137 {
1138         struct cmd_monitor_del_result *res = parsed_result;
1139
1140         (void)data;
1141         monitor_current = LIST_NEXT(res->m, next);
1142         LIST_REMOVE(res->m, next);
1143         free(res->m);
1144         monitor_count --;
1145         if (monitor_count == 0) {
1146                 printf_P(PSTR("Disable monitoring, no more event\r\n"));
1147                 callout_stop(&xbeeboard.intr_cm, &monitor_event);
1148                 monitor_running = 0;
1149                 return;
1150         }
1151 }
1152
1153 const char PROGMEM str_monitor_del[] = "del";
1154
1155 const parse_token_string_t PROGMEM cmd_monitor_del_monitor_del =
1156         TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, monitor,
1157                                  str_monitor);
1158 const parse_token_string_t PROGMEM cmd_monitor_del_action =
1159         TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, action,
1160                                  str_monitor_del);
1161 const parse_token_monitor_t PROGMEM cmd_monitor_del_atcmd =
1162         TOKEN_MONITOR_INITIALIZER(struct cmd_monitor_del_result, m);
1163
1164
1165 const char PROGMEM help_monitor_del[] = "del a register in monitor list";
1166
1167 const parse_inst_t PROGMEM cmd_monitor_del = {
1168         .f = cmd_monitor_del_parsed,  /* function to call */
1169         .data = NULL,      /* 2nd arg of func */
1170         .help_str = help_monitor_del,
1171         .tokens = {        /* token list, NULL terminated */
1172                 (PGM_P)&cmd_monitor_del_monitor_del,
1173                 (PGM_P)&cmd_monitor_del_action,
1174                 (PGM_P)&cmd_monitor_del_atcmd,
1175                 NULL,
1176         },
1177 };
1178
1179
1180 /* ************* */
1181
1182 /* this structure is filled when cmd_ping is parsed successfully */
1183 struct cmd_ping_result {
1184         fixed_string_t ping;
1185 };
1186
1187 /* function called when cmd_ping is parsed successfully */
1188 static void cmd_ping_parsed(void *parsed_result, void *data)
1189 {
1190         volatile uint8_t done = 0;
1191
1192         (void)parsed_result;
1193         (void)data;
1194         xbeeapp_send_atcmd("VL", NULL, 0, dump_xbee_atresp_cb, (void *)&done);
1195         while (done == 0);
1196 }
1197
1198 const char PROGMEM str_ping[] = "ping";
1199
1200 const parse_token_string_t PROGMEM cmd_ping_ping =
1201         TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping,
1202                                  str_ping);
1203
1204 const char PROGMEM help_ping[] = "Send a ping to the xbee device";
1205
1206 const parse_inst_t PROGMEM cmd_ping = {
1207         .f = cmd_ping_parsed,  /* function to call */
1208         .data = NULL,      /* 2nd arg of func */
1209         .help_str = help_ping,
1210         .tokens = {        /* token list, NULL terminated */
1211                 (PGM_P)&cmd_ping_ping,
1212                 NULL,
1213         },
1214 };
1215
1216 /* ************* */
1217
1218 /* this structure is filled when cmd_raw is parsed successfully */
1219 struct cmd_raw_result {
1220         fixed_string_t raw;
1221 };
1222
1223 /* function called when cmd_raw is parsed successfully */
1224 static void cmd_raw_parsed(void *parsed_result, void *data)
1225 {
1226         (void)parsed_result;
1227         (void)data;
1228
1229         if (range_running || monitor_running) {
1230                 printf_P(PSTR("stop running range or monitor first\r\n"));
1231                 return;
1232         }
1233         printf_P(PSTR("switched to raw mode, CTRL-D to exit\r\n"));
1234         rdline_stop(&xbeeboard.rdl); /* don't display prompt when return */
1235         xbee_raw = 1;
1236 }
1237
1238 const char PROGMEM str_raw[] = "raw";
1239
1240 const parse_token_string_t PROGMEM cmd_raw_raw =
1241         TOKEN_STRING_INITIALIZER(struct cmd_raw_result, raw,
1242                                  str_raw);
1243
1244 const char PROGMEM help_raw[] = "Switch to raw mode";
1245
1246 const parse_inst_t PROGMEM cmd_raw = {
1247         .f = cmd_raw_parsed,  /* function to call */
1248         .data = NULL,      /* 2nd arg of func */
1249         .help_str = help_raw,
1250         .tokens = {        /* token list, NULL terminated */
1251                 (PGM_P)&cmd_raw_raw,
1252                 NULL,
1253         },
1254 };
1255
1256 /**********************************************************/
1257
1258 /* this structure is filled when cmd_baudrate is parsed successfully */
1259 struct cmd_baudrate_result {
1260         fixed_string_t arg0;
1261         uint32_t arg1;
1262 };
1263
1264 /* function called when cmd_baudrate is parsed successfully */
1265 static void cmd_baudrate_parsed(void * parsed_result, __attribute__((unused)) void *data)
1266 {
1267         struct cmd_baudrate_result *res = parsed_result;
1268         struct uart_config c;
1269
1270         uart_getconf(XBEE_UART, &c);
1271         c.baudrate = res->arg1;
1272         uart_setconf(XBEE_UART, &c);
1273 }
1274
1275 const char PROGMEM str_baudrate_arg0[] = "baudrate";
1276 const parse_token_string_t PROGMEM cmd_baudrate_arg0 =
1277         TOKEN_STRING_INITIALIZER(struct cmd_baudrate_result, arg0,
1278                                  str_baudrate_arg0);
1279 const parse_token_num_t PROGMEM cmd_baudrate_arg1 =
1280         TOKEN_NUM_INITIALIZER(struct cmd_baudrate_result, arg1,
1281                               UINT32);
1282
1283 const char PROGMEM help_baudrate[] = "Change xbee baudrate";
1284 const parse_inst_t PROGMEM cmd_baudrate = {
1285         .f = cmd_baudrate_parsed,  /* function to call */
1286         .data = NULL,      /* 2nd arg of func */
1287         .help_str = help_baudrate,
1288         .tokens = {        /* token list, NULL terminated */
1289                 (PGM_P)&cmd_baudrate_arg0,
1290                 (PGM_P)&cmd_baudrate_arg1,
1291                 NULL,
1292         },
1293 };
1294
1295
1296 /**********************************************************/
1297
1298 /* this structure is filled when cmd_beep is parsed successfully */
1299 struct cmd_beep_result {
1300         fixed_string_t beep;
1301 };
1302
1303 /* function called when cmd_beep is parsed successfully */
1304 static void cmd_beep_parsed(void *parsed_result, void *data)
1305 {
1306         (void)parsed_result;
1307         (void)data;
1308
1309         beep(0, 3, 3);
1310         beep(1, 3, 3);
1311         beep(2, 3, 3);
1312         beep(0, 1, 1);
1313         beep(1, 1, 1);
1314         beep(2, 1, 1);
1315 }
1316
1317 const char PROGMEM str_beep[] = "beep";
1318 const parse_token_string_t PROGMEM cmd_beep_beep =
1319         TOKEN_STRING_INITIALIZER(struct cmd_beep_result, beep,
1320                                  str_beep);
1321
1322 const char PROGMEM help_beep[] = "Send a beep";
1323
1324 const parse_inst_t PROGMEM cmd_beep = {
1325         .f = cmd_beep_parsed,  /* function to call */
1326         .data = NULL,      /* 2nd arg of func */
1327         .help_str = help_beep,
1328         .tokens = {        /* token list, NULL terminated */
1329                 (PGM_P)&cmd_beep_beep,
1330                 NULL,
1331         },
1332 };
1333
1334 /**********************************************************/
1335
1336 /* this structure is filled when cmd_servo is parsed successfully */
1337 struct cmd_servo_result {
1338         fixed_string_t arg0;
1339         fixed_string_t arg1;
1340         uint16_t num;
1341         uint16_t val;
1342 };
1343
1344 /* function called when cmd_servo is parsed successfully */
1345 static void cmd_servo_parsed(void * parsed_result, void *data)
1346 {
1347         struct cmd_servo_result *res = parsed_result;
1348
1349         (void)data;
1350
1351         if (!strcmp_P(res->arg1, PSTR("set"))) {
1352                 if (res->num >= N_SERVO) {
1353                         printf_P(PSTR("bad servo num\n"));
1354                         return;
1355                 }
1356                 if (res->val >= 1024) {
1357                         printf_P(PSTR("bad servo val\n"));
1358                         return;
1359                 }
1360                 spi_servo_set(res->num, res->val);
1361         }
1362         else if (!strcmp_P(res->arg1, PSTR("bypass"))) {
1363                 spi_servo_set_bypass(!!res->val);
1364         }
1365         else if (!strcmp_P(res->arg1, PSTR("ppm"))) {
1366                 spi_servo_set_ppm(!!res->val);
1367         }
1368         else if (!strcmp_P(res->arg1, PSTR("show"))) {
1369                 spi_servo_dump();
1370         }
1371 }
1372
1373 const char PROGMEM str_servo_arg0[] = "servo";
1374 const parse_token_string_t PROGMEM cmd_servo_arg0 =
1375         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg0,
1376                                  str_servo_arg0);
1377 const char PROGMEM str_servo_arg1_set[] = "set";
1378 const parse_token_string_t PROGMEM cmd_servo_arg1_set =
1379         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1380                                  str_servo_arg1_set);
1381 const parse_token_num_t PROGMEM cmd_servo_num =
1382         TOKEN_NUM_INITIALIZER(struct cmd_servo_result, num,
1383                               UINT16);
1384 const parse_token_num_t PROGMEM cmd_servo_val =
1385         TOKEN_NUM_INITIALIZER(struct cmd_servo_result, val,
1386                               UINT16);
1387
1388 const char PROGMEM help_servo_set[] = "set servo value";
1389 const parse_inst_t PROGMEM cmd_servo_set = {
1390         .f = cmd_servo_parsed,  /* function to call */
1391         .data = NULL,      /* 2nd arg of func */
1392         .help_str = help_servo_set,
1393         .tokens = {        /* token list, NULL terminated */
1394                 (PGM_P)&cmd_servo_arg0,
1395                 (PGM_P)&cmd_servo_arg1_set,
1396                 (PGM_P)&cmd_servo_num,
1397                 (PGM_P)&cmd_servo_val,
1398                 NULL,
1399         },
1400 };
1401
1402 const char PROGMEM str_servo_arg1_show[] = "show";
1403 const parse_token_string_t PROGMEM cmd_servo_arg1_show =
1404         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1405                                  str_servo_arg1_show);
1406
1407 const char PROGMEM help_servo_show[] = "read servo and config";
1408 const parse_inst_t PROGMEM cmd_servo_show = {
1409         .f = cmd_servo_parsed,  /* function to call */
1410         .data = NULL,      /* 2nd arg of func */
1411         .help_str = help_servo_show,
1412         .tokens = {        /* token list, NULL terminated */
1413                 (PGM_P)&cmd_servo_arg0,
1414                 (PGM_P)&cmd_servo_arg1_show,
1415                 NULL,
1416         },
1417 };
1418
1419 const char PROGMEM str_servo_arg1_bypassppm[] = "bypass#ppm";
1420 const parse_token_string_t PROGMEM cmd_servo_arg1_bypassppm =
1421         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1422                                  str_servo_arg1_bypassppm);
1423
1424 const char PROGMEM help_servo_bypassppm[] = "change bypass/ppm";
1425 const parse_inst_t PROGMEM cmd_servo_bypassppm = {
1426         .f = cmd_servo_parsed,  /* function to call */
1427         .data = NULL,      /* 2nd arg of func */
1428         .help_str = help_servo_bypassppm,
1429         .tokens = {        /* token list, NULL terminated */
1430                 (PGM_P)&cmd_servo_arg0,
1431                 (PGM_P)&cmd_servo_arg1_bypassppm,
1432                 (PGM_P)&cmd_servo_val,
1433                 NULL,
1434         },
1435 };
1436
1437 /**********************************************************/
1438
1439 /* this structure is filled when cmd_test_spi is parsed successfully */
1440 struct cmd_test_spi_result {
1441         fixed_string_t arg0;
1442 };
1443
1444 static void cmd_test_spi_parsed(void * parsed_result, void *data)
1445 {
1446         uint8_t i, flags, wait_time = 0;
1447         uint16_t val = 0;
1448
1449         (void)parsed_result;
1450         (void)data;
1451
1452         spi_servo_set_bypass(0);
1453         spi_servo_set_ppm(0);
1454
1455         /* stress test: send many commands, no wait between each servo
1456          * of a series, and a variable delay between series */
1457         printf_P(PSTR("stress test\r\n"));
1458         while (!cmdline_keypressed()) {
1459
1460                 wait_time++;
1461                 if (wait_time > 20)
1462                         wait_time = 0;
1463
1464                 IRQ_LOCK(flags);
1465                 val = global_ms;
1466                 IRQ_UNLOCK(flags);
1467                 val >>= 3;
1468                 val &= 1023;
1469
1470                 for (i = 0; i < 6; i++)
1471                         spi_servo_set(i, val);
1472
1473                 wait_ms(wait_time);
1474                 printf_P(PSTR("%4.4d %4.4d %4.4d %4.4d %4.4d %4.4d\r\n"),
1475                          spi_servo_get(0), spi_servo_get(1), spi_servo_get(2),
1476                          spi_servo_get(3), spi_servo_get(4), spi_servo_get(5));
1477         }
1478
1479         printf_P(PSTR("bypass mode, with spi commands in background\r\n"));
1480         spi_servo_set_bypass(1);
1481
1482         /* test bypass mode */
1483         while (!cmdline_keypressed()) {
1484
1485                 wait_time++;
1486                 if (wait_time > 20)
1487                         wait_time = 0;
1488
1489                 IRQ_LOCK(flags);
1490                 val = global_ms;
1491                 IRQ_UNLOCK(flags);
1492                 val >>= 3;
1493                 val &= 1023;
1494
1495                 for (i = 0; i < 6; i++)
1496                         spi_servo_set(i, val);
1497
1498                 wait_ms(wait_time);
1499                 printf_P(PSTR("%4.4d %4.4d %4.4d %4.4d %4.4d %4.4d\r\n"),
1500                          spi_servo_get(0), spi_servo_get(1), spi_servo_get(2),
1501                          spi_servo_get(3), spi_servo_get(4), spi_servo_get(5));
1502         }
1503
1504         printf_P(PSTR("PPM to servo\r\n"));
1505         spi_servo_set_bypass(0);
1506         spi_servo_set_ppm(0);
1507
1508         /* test PPM to servo (bypass) mode */
1509         while (!cmdline_keypressed()) {
1510                 for (i = 0; i < 6; i++) {
1511                         val = spi_servo_get(i);
1512                         spi_servo_set(i, val);
1513                 }
1514         }
1515
1516         printf_P(PSTR("PPM to (servo + PPM)\r\n"));
1517         spi_servo_set_bypass(0);
1518         spi_servo_set_ppm(1);
1519
1520         /* test PPM to servo (bypass) mode */
1521         while (!cmdline_keypressed()) {
1522                 for (i = 0; i < 6; i++) {
1523                         val = spi_servo_get(i);
1524                         spi_servo_set(i, val);
1525                 }
1526         }
1527 }
1528
1529 const char PROGMEM str_test_spi_arg0[] = "test_spi";
1530 const parse_token_string_t PROGMEM cmd_test_spi_arg0 =
1531         TOKEN_STRING_INITIALIZER(struct cmd_test_spi_result, arg0,
1532                                  str_test_spi_arg0);
1533
1534 const char PROGMEM help_test_spi[] = "Test the spi";
1535 const parse_inst_t PROGMEM cmd_test_spi = {
1536         .f = cmd_test_spi_parsed,  /* function to call */
1537         .data = NULL,      /* 2nd arg of func */
1538         .help_str = help_test_spi,
1539         .tokens = {        /* token list, NULL terminated */
1540                 (PGM_P)&cmd_test_spi_arg0,
1541                 NULL,
1542         },
1543 };
1544
1545 /**********************************************************/
1546
1547 /* this structure is filled when cmd_dump_xbee_stats is parsed successfully */
1548 struct cmd_dump_xbee_stats_result {
1549         fixed_string_t arg0;
1550 };
1551
1552 static void cmd_dump_xbee_stats_parsed(void *parsed_result, void *data)
1553 {
1554         (void)parsed_result;
1555         (void)data;
1556
1557         xbee_dump_stats(xbee_dev);
1558 }
1559
1560 const char PROGMEM str_dump_xbee_stats_arg0[] = "dump_xbee_stats";
1561 const parse_token_string_t PROGMEM cmd_dump_xbee_stats_arg0 =
1562         TOKEN_STRING_INITIALIZER(struct cmd_dump_xbee_stats_result, arg0,
1563                                  str_dump_xbee_stats_arg0);
1564
1565 const char PROGMEM help_dump_xbee_stats[] = "Test the spi";
1566 const parse_inst_t PROGMEM cmd_dump_xbee_stats = {
1567         .f = cmd_dump_xbee_stats_parsed,  /* function to call */
1568         .data = NULL,      /* 2nd arg of func */
1569         .help_str = help_dump_xbee_stats,
1570         .tokens = {        /* token list, NULL terminated */
1571                 (PGM_P)&cmd_dump_xbee_stats_arg0,
1572                 NULL,
1573         },
1574 };
1575
1576 /**********************************************************/
1577
1578 /* this structure is filled when cmd_rc_proto_stats is parsed successfully */
1579 struct cmd_rc_proto_stats_result {
1580         fixed_string_t arg0;
1581         fixed_string_t arg1;
1582 };
1583
1584 static void cmd_rc_proto_stats_parsed(void *parsed_result, void *data)
1585 {
1586         struct cmd_rc_proto_stats_result *res = parsed_result;
1587         (void)data;
1588
1589         if (!strcmp(res->arg1, "show"))
1590                 rc_proto_dump_stats();
1591         else /* reset */
1592                 rc_proto_reset_stats();
1593 }
1594
1595 const char PROGMEM str_rc_proto_stats_arg0[] = "rc_proto_stats";
1596 const parse_token_string_t PROGMEM cmd_rc_proto_stats_arg0 =
1597         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_stats_result, arg0,
1598                                  str_rc_proto_stats_arg0);
1599 const char PROGMEM str_rc_proto_stats_arg1[] = "show#reset";
1600 const parse_token_string_t PROGMEM cmd_rc_proto_stats_arg1 =
1601         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_stats_result, arg1,
1602                                  str_rc_proto_stats_arg1);
1603
1604 const char PROGMEM help_rc_proto_stats[] = "dump rc_proto stats";
1605 const parse_inst_t PROGMEM cmd_rc_proto_stats = {
1606         .f = cmd_rc_proto_stats_parsed,  /* function to call */
1607         .data = NULL,      /* 2nd arg of func */
1608         .help_str = help_rc_proto_stats,
1609         .tokens = {        /* token list, NULL terminated */
1610                 (PGM_P)&cmd_rc_proto_stats_arg0,
1611                 (PGM_P)&cmd_rc_proto_stats_arg1,
1612                 NULL,
1613         },
1614 };
1615
1616 /**********************************************************/
1617
1618 /* this structure is filled when cmd_rc_proto_timers is parsed successfully */
1619 struct cmd_rc_proto_timers_result {
1620         fixed_string_t arg0;
1621         fixed_string_t arg1;
1622         uint16_t servo_min;
1623         uint16_t servo_max;
1624         uint16_t power_probe;
1625         uint16_t autobypass;
1626 };
1627
1628 static void cmd_rc_proto_timers_parsed(void *parsed_result, void *data)
1629 {
1630         struct cmd_rc_proto_timers_result *res = parsed_result;
1631         (void)data;
1632
1633         if (!strcmp_P(res->arg1, PSTR("set"))) {
1634                 rc_proto_timers.send_servo_min_ms = res->servo_min;
1635                 rc_proto_timers.send_servo_max_ms = res->servo_max;
1636                 rc_proto_timers.send_power_probe_ms = res->power_probe;
1637                 rc_proto_timers.autobypass_ms = res->autobypass;
1638         }
1639
1640         printf_P(PSTR("rc_proto_timers: min=%d, max=%d, "
1641                         "power_probe=%d autobypass=%d\n"),
1642                 rc_proto_timers.send_servo_min_ms,
1643                 rc_proto_timers.send_servo_max_ms,
1644                 rc_proto_timers.send_power_probe_ms,
1645                 rc_proto_timers.autobypass_ms);
1646 }
1647
1648 const char PROGMEM str_rc_proto_timers_arg0[] = "rc_proto_timers";
1649 const parse_token_string_t PROGMEM cmd_rc_proto_timers_arg0 =
1650         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_timers_result, arg0,
1651                                  str_rc_proto_timers_arg0);
1652 const char PROGMEM str_rc_proto_timers_arg1[] = "set";
1653 const parse_token_string_t PROGMEM cmd_rc_proto_timers_arg1 =
1654         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_timers_result, arg1,
1655                                  str_rc_proto_timers_arg1);
1656 const parse_token_num_t PROGMEM cmd_rc_proto_timers_servo_min =
1657         TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, servo_min,
1658                 UINT16);
1659 const parse_token_num_t PROGMEM cmd_rc_proto_timers_servo_max =
1660         TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, servo_max,
1661                 UINT16);
1662 const parse_token_num_t PROGMEM cmd_rc_proto_timers_power_probe =
1663         TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, power_probe,
1664                 UINT16);
1665 const parse_token_num_t PROGMEM cmd_rc_proto_timers_autobypass =
1666         TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_timers_result, autobypass,
1667                 UINT16);
1668
1669 const char PROGMEM help_rc_proto_timers[] = "set rc_proto_timers (servo_min, "
1670         "servo_max, pow_probe, autobypass)";
1671 const parse_inst_t PROGMEM cmd_rc_proto_timers = {
1672         .f = cmd_rc_proto_timers_parsed,  /* function to call */
1673         .data = NULL,      /* 2nd arg of func */
1674         .help_str = help_rc_proto_timers,
1675         .tokens = {        /* token list, NULL terminated */
1676                 (PGM_P)&cmd_rc_proto_timers_arg0,
1677                 (PGM_P)&cmd_rc_proto_timers_arg1,
1678                 (PGM_P)&cmd_rc_proto_timers_servo_min,
1679                 (PGM_P)&cmd_rc_proto_timers_servo_max,
1680                 (PGM_P)&cmd_rc_proto_timers_power_probe,
1681                 (PGM_P)&cmd_rc_proto_timers_autobypass,
1682                 NULL,
1683         },
1684 };
1685
1686 const char PROGMEM str_rc_proto_timers_show_arg1[] = "show";
1687 const parse_token_string_t PROGMEM cmd_rc_proto_timers_show_arg1 =
1688         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_timers_result, arg1,
1689                                  str_rc_proto_timers_show_arg1);
1690
1691 const char PROGMEM help_rc_proto_timers_show[] = "show rc_proto timers value";
1692 const parse_inst_t PROGMEM cmd_rc_proto_timers_show = {
1693         .f = cmd_rc_proto_timers_parsed,  /* function to call */
1694         .data = NULL,      /* 2nd arg of func */
1695         .help_str = help_rc_proto_timers_show,
1696         .tokens = {        /* token list, NULL terminated */
1697                 (PGM_P)&cmd_rc_proto_timers_arg0,
1698                 (PGM_P)&cmd_rc_proto_timers_show_arg1,
1699                 NULL,
1700         },
1701 };
1702
1703 /**********************************************************/
1704
1705 /* this structure is filled when cmd_rc_proto_mode is parsed successfully */
1706 struct cmd_rc_proto_mode_result {
1707         fixed_string_t arg0;
1708         fixed_string_t cmd;
1709         fixed_string_t val;
1710 };
1711
1712 static void cmd_rc_proto_mode_parsed(void *parsed_result, void *data)
1713 {
1714         struct cmd_rc_proto_mode_result *res = parsed_result;
1715         (void)data;
1716         uint8_t flags;
1717         uint8_t on = 0;
1718
1719         flags = rc_proto_get_mode();
1720         if (!strcmp_P(res->val, PSTR("on")))
1721                 on = 1;
1722
1723         if (!strcmp_P(res->cmd, PSTR("rx_copy_spi"))) {
1724                 if (on == 1)
1725                         flags |= RC_PROTO_FLAGS_RX_COPY_SPI;
1726                 else
1727                         flags &= ~RC_PROTO_FLAGS_RX_COPY_SPI;
1728         }
1729         else if (!strcmp_P(res->cmd, PSTR("rx_autobypass"))) {
1730                 if (on == 1)
1731                         flags |= RC_PROTO_FLAGS_RX_AUTOBYPASS;
1732                 else
1733                         flags &= ~RC_PROTO_FLAGS_RX_AUTOBYPASS;
1734         }
1735         else if (!strcmp_P(res->cmd, PSTR("tx_stats"))) {
1736                 if (on == 1)
1737                         flags |= RC_PROTO_FLAGS_TX_STATS;
1738                 else
1739                         flags &= ~RC_PROTO_FLAGS_TX_STATS;
1740         }
1741         else if (!strcmp_P(res->cmd, PSTR("tx_power_probe"))) {
1742                 if (on == 1)
1743                         flags |= RC_PROTO_FLAGS_TX_POW_PROBE;
1744                 else
1745                         flags &= ~RC_PROTO_FLAGS_TX_POW_PROBE;
1746         }
1747         else if (!strcmp_P(res->cmd, PSTR("compute_best_pow"))) {
1748                 if (on == 1)
1749                         flags |= RC_PROTO_FLAGS_COMPUTE_BEST_POW;
1750                 else
1751                         flags &= ~RC_PROTO_FLAGS_COMPUTE_BEST_POW;
1752         }
1753         else if (!strcmp_P(res->cmd, PSTR("tx"))) {
1754                 flags &= ~RC_PROTO_FLAGS_TX_MASK;
1755                 if (!strcmp_P(res->val, PSTR("bypass")))
1756                         flags |= RC_PROTO_FLAGS_TX_BYPASS;
1757                 else if (!strcmp_P(res->val, PSTR("copy_spi")))
1758                         flags |= RC_PROTO_FLAGS_TX_COPY_SPI;
1759         }
1760         rc_proto_set_mode(flags);
1761
1762         /* dump state */
1763         if ((flags & RC_PROTO_FLAGS_TX_MASK) == RC_PROTO_FLAGS_TX_OFF)
1764                 printf_P(PSTR("rc_proto_mode tx off\n"));
1765         else if ((flags & RC_PROTO_FLAGS_TX_MASK) == RC_PROTO_FLAGS_TX_BYPASS)
1766                 printf_P(PSTR("rc_proto_mode tx bypass\n"));
1767         else if ((flags & RC_PROTO_FLAGS_TX_MASK) == RC_PROTO_FLAGS_TX_COPY_SPI)
1768                 printf_P(PSTR("rc_proto_mode tx copy_spi\n"));
1769         printf_P(PSTR("rc_proto_mode rx_copy_spi %s\n"),
1770                 (flags & RC_PROTO_FLAGS_RX_COPY_SPI) ? "on" : "off");
1771         printf_P(PSTR("rc_proto_mode rx_autobypass %s\n"),
1772                 (flags & RC_PROTO_FLAGS_RX_AUTOBYPASS) ? "on" : "off");
1773         printf_P(PSTR("rc_proto_mode tx_stats %s\n"),
1774                 (flags & RC_PROTO_FLAGS_TX_STATS) ? "on" : "off");
1775         printf_P(PSTR("rc_proto_mode tx_power_probe %s\n"),
1776                 (flags & RC_PROTO_FLAGS_TX_POW_PROBE) ? "on" : "off");
1777         printf_P(PSTR("rc_proto_mode compute_best_pow %s\n"),
1778                 (flags & RC_PROTO_FLAGS_COMPUTE_BEST_POW) ? "on" : "off");
1779 }
1780
1781 const char PROGMEM str_rc_proto_mode_arg0[] = "rc_proto_mode";
1782 const parse_token_string_t PROGMEM cmd_rc_proto_mode_arg0 =
1783         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, arg0,
1784                                  str_rc_proto_mode_arg0);
1785
1786 const char PROGMEM str_rc_proto_mode_cmd[] =
1787         "rx_copy_spi#rx_autobypass#tx_stats#tx_power_probe#compute_best_pow";
1788 const parse_token_string_t PROGMEM cmd_rc_proto_mode_cmd =
1789         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, cmd,
1790                 str_rc_proto_mode_cmd);
1791
1792 const char PROGMEM str_rc_proto_mode_onoff[] = "on#off";
1793 const parse_token_string_t PROGMEM cmd_rc_proto_mode_onoff =
1794         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, val,
1795                                  str_rc_proto_mode_onoff);
1796
1797 const char PROGMEM help_rc_proto_mode[] = "Set rc proto behavior";
1798 const parse_inst_t PROGMEM cmd_rc_proto_mode = {
1799         .f = cmd_rc_proto_mode_parsed,  /* function to call */
1800         .data = NULL,      /* 2nd arg of func */
1801         .help_str = help_rc_proto_mode,
1802         .tokens = {        /* token list, NULL terminated */
1803                 (PGM_P)&cmd_rc_proto_mode_arg0,
1804                 (PGM_P)&cmd_rc_proto_mode_cmd,
1805                 (PGM_P)&cmd_rc_proto_mode_onoff,
1806                 NULL,
1807         },
1808 };
1809
1810 const char PROGMEM str_rc_proto_mode_cmd2[] = "tx";
1811 const parse_token_string_t PROGMEM cmd_rc_proto_mode_cmd2 =
1812         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, cmd,
1813                 str_rc_proto_mode_cmd2);
1814
1815 const char PROGMEM str_rc_proto_mode_val[] = "off#bypass#copy_spi";
1816 const parse_token_string_t PROGMEM cmd_rc_proto_mode_val =
1817         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, val,
1818                                  str_rc_proto_mode_val);
1819
1820 const parse_inst_t PROGMEM cmd_rc_proto_mode2 = {
1821         .f = cmd_rc_proto_mode_parsed,  /* function to call */
1822         .data = NULL,      /* 2nd arg of func */
1823         .help_str = help_rc_proto_mode,
1824         .tokens = {        /* token list, NULL terminated */
1825                 (PGM_P)&cmd_rc_proto_mode_arg0,
1826                 (PGM_P)&cmd_rc_proto_mode_cmd2,
1827                 (PGM_P)&cmd_rc_proto_mode_val,
1828                 NULL,
1829         },
1830 };
1831
1832 const char PROGMEM str_rc_proto_mode_cmd3[] = "show";
1833 const parse_token_string_t PROGMEM cmd_rc_proto_mode_cmd3 =
1834         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_mode_result, cmd,
1835                 str_rc_proto_mode_cmd3);
1836
1837 const parse_inst_t PROGMEM cmd_rc_proto_mode3 = {
1838         .f = cmd_rc_proto_mode_parsed,  /* function to call */
1839         .data = NULL,      /* 2nd arg of func */
1840         .help_str = help_rc_proto_mode,
1841         .tokens = {        /* token list, NULL terminated */
1842                 (PGM_P)&cmd_rc_proto_mode_arg0,
1843                 (PGM_P)&cmd_rc_proto_mode_cmd3,
1844                 NULL,
1845         },
1846 };
1847
1848 /**********************************************************/
1849
1850 /* this structure is filled when cmd_rc_proto_hello is parsed successfully */
1851 struct cmd_rc_proto_hello_result {
1852         fixed_string_t rc_proto_hello;
1853         uint64_t addr;
1854         struct xbee_neigh *neigh;
1855         uint16_t period;
1856         uint16_t count;
1857         fixed_string_t data;
1858 };
1859
1860 /* function called when cmd_rc_proto_hello is parsed successfully */
1861 static void cmd_rc_proto_hello_parsed(void *parsed_result, void *use_neigh)
1862 {
1863         struct cmd_rc_proto_hello_result *res = parsed_result;
1864         uint16_t now, next, diff;
1865         uint8_t flags;
1866         uint64_t addr;
1867
1868         if (use_neigh)
1869                 addr = res->neigh->addr;
1870         else
1871                 addr = res->addr;
1872
1873         IRQ_LOCK(flags);
1874         now = global_ms;
1875         IRQ_UNLOCK(flags);
1876
1877         next = now;
1878
1879         while (!cmdline_keypressed() && res->count != 0) {
1880                 IRQ_LOCK(flags);
1881                 now = global_ms;
1882                 IRQ_UNLOCK(flags);
1883
1884                 diff = now - next;
1885                 if (diff < res->period)
1886                         continue;
1887
1888                 rc_proto_send_hello(addr, res->data, strlen(res->data), -1);
1889                 next += res->period;
1890                 res->count--;
1891         }
1892 }
1893
1894 const char PROGMEM str_rc_proto_hello[] = "rc_proto_hello";
1895
1896 const parse_token_string_t PROGMEM cmd_rc_proto_hello_rc_proto_hello =
1897         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_hello_result, rc_proto_hello,
1898                                  str_rc_proto_hello);
1899
1900 const parse_token_num_t PROGMEM cmd_rc_proto_hello_addr =
1901         TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_hello_result, addr, UINT64);
1902
1903 const parse_token_num_t PROGMEM cmd_rc_proto_hello_period =
1904         TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_hello_result, period, UINT16);
1905
1906 const parse_token_num_t PROGMEM cmd_rc_proto_hello_count =
1907         TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_hello_result, count, UINT16);
1908
1909 const parse_token_string_t PROGMEM cmd_rc_proto_hello_data =
1910         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_hello_result, data, NULL);
1911
1912 const char PROGMEM help_rc_proto_hello[] =
1913         "Send hello msg to a node: addr, period_ms, count, str";
1914
1915 const parse_inst_t PROGMEM cmd_rc_proto_hello = {
1916         .f = cmd_rc_proto_hello_parsed,  /* function to call */
1917         .data = NULL,      /* 2nd arg of func */
1918         .help_str = help_rc_proto_hello,
1919         .tokens = {        /* token list, NULL terminated */
1920                 (PGM_P)&cmd_rc_proto_hello_rc_proto_hello,
1921                 (PGM_P)&cmd_rc_proto_hello_addr,
1922                 (PGM_P)&cmd_rc_proto_hello_period,
1923                 (PGM_P)&cmd_rc_proto_hello_count,
1924                 (PGM_P)&cmd_rc_proto_hello_data,
1925                 NULL,
1926         },
1927 };
1928
1929 const parse_token_neighbor_t PROGMEM cmd_rc_proto_hello_neigh =
1930         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_rc_proto_hello_result, neigh,
1931                                    &xbee_dev);
1932
1933 const parse_inst_t PROGMEM cmd_rc_proto_hello_name = {
1934         .f = cmd_rc_proto_hello_parsed,  /* function to call */
1935         .data = (void *)1,      /* 2nd arg of func */
1936         .help_str = help_rc_proto_hello,
1937         .tokens = {        /* token list, NULL terminated */
1938                 (PGM_P)&cmd_rc_proto_hello_rc_proto_hello,
1939                 (PGM_P)&cmd_rc_proto_hello_neigh,
1940                 (PGM_P)&cmd_rc_proto_hello_period,
1941                 (PGM_P)&cmd_rc_proto_hello_count,
1942                 (PGM_P)&cmd_rc_proto_hello_data,
1943                 NULL,
1944         },
1945 };
1946
1947 /**********************************************************/
1948
1949 /* this structure is filled when cmd_rc_proto_echo is parsed successfully */
1950 struct cmd_rc_proto_echo_result {
1951         fixed_string_t rc_proto_echo;
1952         uint64_t addr;
1953         struct xbee_neigh *neigh;
1954         uint16_t period;
1955         uint16_t count;
1956         fixed_string_t data;
1957 };
1958
1959 /* function called when cmd_rc_proto_echo is parsed successfully */
1960 static void cmd_rc_proto_echo_parsed(void *parsed_result, void *use_neigh)
1961 {
1962         struct cmd_rc_proto_echo_result *res = parsed_result;
1963         uint16_t now, next, diff;
1964         uint8_t flags;
1965         uint64_t addr;
1966
1967         if (use_neigh)
1968                 addr = res->neigh->addr;
1969         else
1970                 addr = res->addr;
1971
1972         IRQ_LOCK(flags);
1973         now = global_ms;
1974         IRQ_UNLOCK(flags);
1975
1976         next = now;
1977
1978         while (!cmdline_keypressed() && res->count != 0) {
1979                 IRQ_LOCK(flags);
1980                 now = global_ms;
1981                 IRQ_UNLOCK(flags);
1982
1983                 diff = now - next;
1984                 if (diff < res->period)
1985                         continue;
1986
1987                 rc_proto_send_echo_req(addr, res->data, strlen(res->data), -1);
1988                 next += res->period;
1989                 res->count--;
1990         }
1991 }
1992
1993 const char PROGMEM str_rc_proto_echo[] = "rc_proto_echo";
1994
1995 const parse_token_string_t PROGMEM cmd_rc_proto_echo_rc_proto_echo =
1996         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_echo_result, rc_proto_echo,
1997                                  str_rc_proto_echo);
1998
1999 const parse_token_num_t PROGMEM cmd_rc_proto_echo_addr =
2000         TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_echo_result, addr, UINT64);
2001
2002 const parse_token_num_t PROGMEM cmd_rc_proto_echo_period =
2003         TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_echo_result, period, UINT16);
2004
2005 const parse_token_num_t PROGMEM cmd_rc_proto_echo_count =
2006         TOKEN_NUM_INITIALIZER(struct cmd_rc_proto_echo_result, count, UINT16);
2007
2008 const parse_token_string_t PROGMEM cmd_rc_proto_echo_data =
2009         TOKEN_STRING_INITIALIZER(struct cmd_rc_proto_echo_result, data, NULL);
2010
2011 const char PROGMEM help_rc_proto_echo[] =
2012         "Send echo msg to a node: addr, period_ms, count, str";
2013
2014 const parse_inst_t PROGMEM cmd_rc_proto_echo = {
2015         .f = cmd_rc_proto_echo_parsed,  /* function to call */
2016         .data = NULL,      /* 2nd arg of func */
2017         .help_str = help_rc_proto_echo,
2018         .tokens = {        /* token list, NULL terminated */
2019                 (PGM_P)&cmd_rc_proto_echo_rc_proto_echo,
2020                 (PGM_P)&cmd_rc_proto_echo_addr,
2021                 (PGM_P)&cmd_rc_proto_echo_period,
2022                 (PGM_P)&cmd_rc_proto_echo_count,
2023                 (PGM_P)&cmd_rc_proto_echo_data,
2024                 NULL,
2025         },
2026 };
2027
2028 const parse_token_neighbor_t PROGMEM cmd_rc_proto_echo_neigh =
2029         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_rc_proto_echo_result, neigh,
2030                                    &xbee_dev);
2031
2032 const parse_inst_t PROGMEM cmd_rc_proto_echo_name = {
2033         .f = cmd_rc_proto_echo_parsed,  /* function to call */
2034         .data = (void *)1,      /* 2nd arg of func */
2035         .help_str = help_rc_proto_echo,
2036         .tokens = {        /* token list, NULL terminated */
2037                 (PGM_P)&cmd_rc_proto_echo_rc_proto_echo,
2038                 (PGM_P)&cmd_rc_proto_echo_neigh,
2039                 (PGM_P)&cmd_rc_proto_echo_period,
2040                 (PGM_P)&cmd_rc_proto_echo_count,
2041                 (PGM_P)&cmd_rc_proto_echo_data,
2042                 NULL,
2043         },
2044 };
2045
2046 /**********************************************************/
2047
2048 /* this structure is filled when cmd_test_eeprom_config is parsed successfully */
2049 struct cmd_test_eeprom_config_result {
2050         fixed_string_t arg0;
2051 };
2052
2053 static void cmd_test_eeprom_config_parsed(void *parsed_result, void *data)
2054 {
2055         (void)parsed_result;
2056         (void)data;
2057
2058         eeprom_dump_cmds();
2059         eeprom_append_cmd("salut1\n");
2060         eeprom_dump_cmds();
2061         eeprom_append_cmd("salut2\n");
2062         eeprom_append_cmd("salut3\n");
2063         eeprom_append_cmd("salut4\n");
2064         eeprom_dump_cmds();
2065         eeprom_insert_cmd_before("coin\n", 0);
2066         eeprom_insert_cmd_before("coin2\n", 2);
2067         eeprom_dump_cmds();
2068         eeprom_delete_cmd(2);
2069         eeprom_delete_cmd(0);
2070         eeprom_dump_cmds();
2071 }
2072
2073 const char PROGMEM str_test_eeprom_config_arg0[] = "test_eeprom_config";
2074 const parse_token_string_t PROGMEM cmd_test_eeprom_config_arg0 =
2075         TOKEN_STRING_INITIALIZER(struct cmd_test_eeprom_config_result, arg0,
2076                                  str_test_eeprom_config_arg0);
2077
2078 const char PROGMEM help_test_eeprom_config[] = "Test the eeprom configuration";
2079 const parse_inst_t PROGMEM cmd_test_eeprom_config = {
2080         .f = cmd_test_eeprom_config_parsed,  /* function to call */
2081         .data = NULL,      /* 2nd arg of func */
2082         .help_str = help_test_eeprom_config,
2083         .tokens = {        /* token list, NULL terminated */
2084                 (PGM_P)&cmd_test_eeprom_config_arg0,
2085                 NULL,
2086         },
2087 };
2088
2089 /* ************* */
2090
2091 struct cmd_eeprom_del_result {
2092         fixed_string_t cmd;
2093         fixed_string_t action;
2094         uint8_t n;
2095 };
2096
2097 static void cmd_eeprom_del_parsed(void *parsed_result,
2098                                 void *data)
2099 {
2100         struct cmd_eeprom_del_result *res = parsed_result;
2101
2102         (void)data;
2103         if (eeprom_delete_cmd(res->n) < 0)
2104                 printf_P(PSTR("cannot delete command\n"));
2105         eeprom_dump_cmds();
2106 }
2107
2108 const char PROGMEM str_eeprom_del_eeprom[] = "eeprom";
2109 const parse_token_string_t PROGMEM cmd_eeprom_del_cmd =
2110         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_del_result, cmd,
2111                                  str_eeprom_del_eeprom);
2112 const char PROGMEM str_eeprom_del_del[] = "del";
2113 const parse_token_string_t PROGMEM cmd_eeprom_del_action =
2114         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_del_result, action,
2115                                  str_eeprom_del_del);
2116 const parse_token_num_t PROGMEM cmd_eeprom_del_num =
2117         TOKEN_NUM_INITIALIZER(struct cmd_eeprom_del_result, n,
2118                               UINT8);
2119
2120 const char PROGMEM help_eeprom_del[] = "delete an eeprom init command";
2121 const parse_inst_t PROGMEM cmd_eeprom_del = {
2122         .f = cmd_eeprom_del_parsed,  /* function to call */
2123         .data = NULL,      /* 2nd arg of func */
2124         .help_str = help_eeprom_del,
2125         .tokens = {        /* token list, NULL terminated */
2126                 (PGM_P)&cmd_eeprom_del_cmd,
2127                 (PGM_P)&cmd_eeprom_del_action,
2128                 (PGM_P)&cmd_eeprom_del_num,
2129                 NULL,
2130         },
2131 };
2132
2133 /* ************* */
2134
2135 struct cmd_eeprom_add_result {
2136         fixed_string_t cmd;
2137         fixed_string_t action;
2138         uint8_t n;
2139 };
2140
2141 static void cmd_eeprom_add_parsed(void *parsed_result,
2142                                  void *data)
2143 {
2144         struct cmd_eeprom_add_result *res = parsed_result;
2145         struct rdline rdl;
2146         const char *buffer;
2147         int8_t ret;
2148         int16_t c;
2149
2150         rdline_init(&rdl, cmdline_write_char, NULL, NULL);
2151         rdline_newline(&rdl, "> ");
2152
2153         while (1) {
2154                 c = cmdline_dev_recv(NULL);
2155                 if (c < 0)
2156                         continue;
2157
2158                 ret = rdline_char_in(&rdl, c);
2159                 if (ret == -2) {
2160                         printf_P(PSTR("abort\n"));
2161                         return;
2162                 }
2163                 if (ret == 1)
2164                         break;
2165         }
2166
2167         buffer = rdline_get_buffer(&rdl);
2168         if (data == NULL)
2169                 eeprom_insert_cmd_before(buffer, res->n);
2170         else
2171                 eeprom_append_cmd(buffer);
2172         eeprom_dump_cmds();
2173 }
2174
2175 const char PROGMEM str_eeprom_add_eeprom[] = "eeprom";
2176 const parse_token_string_t PROGMEM cmd_eeprom_add_cmd =
2177         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_add_result, cmd,
2178                                  str_eeprom_add_eeprom);
2179 const char PROGMEM str_eeprom_add_add[] = "add";
2180 const parse_token_string_t PROGMEM cmd_eeprom_add_action =
2181         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_add_result, action,
2182                                  str_eeprom_add_add);
2183 const parse_token_num_t PROGMEM cmd_eeprom_add_num =
2184         TOKEN_NUM_INITIALIZER(struct cmd_eeprom_add_result, n,
2185                               UINT8);
2186
2187 const char PROGMEM help_eeprom_add[] = "insert an eeprom init command";
2188 const parse_inst_t PROGMEM cmd_eeprom_add = {
2189         .f = cmd_eeprom_add_parsed,  /* function to call */
2190         .data = NULL,      /* 2nd arg of func */
2191         .help_str = help_eeprom_add,
2192         .tokens = {        /* token list, NULL terminated */
2193                 (PGM_P)&cmd_eeprom_add_cmd,
2194                 (PGM_P)&cmd_eeprom_add_action,
2195                 (PGM_P)&cmd_eeprom_add_num,
2196                 NULL,
2197         },
2198 };
2199
2200 const char PROGMEM help_eeprom_add2[] = "append an eeprom init command";
2201 const parse_inst_t PROGMEM cmd_eeprom_add2 = {
2202         .f = cmd_eeprom_add_parsed,  /* function to call */
2203         .data = (void *)1,      /* 2nd arg of func */
2204         .help_str = help_eeprom_add2,
2205         .tokens = {        /* token list, NULL terminated */
2206                 (PGM_P)&cmd_eeprom_add_cmd,
2207                 (PGM_P)&cmd_eeprom_add_action,
2208                 NULL,
2209         },
2210 };
2211
2212 /* ************* */
2213
2214 struct cmd_eeprom_list_result {
2215         fixed_string_t cmd;
2216         fixed_string_t action;
2217 };
2218
2219 static void cmd_eeprom_list_parsed(void *parsed_result,
2220                                 void *data)
2221 {
2222         (void)parsed_result;
2223         (void)data;
2224         eeprom_dump_cmds();
2225 }
2226
2227 const char PROGMEM str_eeprom_list_eeprom[] = "eeprom";
2228 const parse_token_string_t PROGMEM cmd_eeprom_list_cmd =
2229         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_list_result, cmd,
2230                                  str_eeprom_list_eeprom);
2231 const char PROGMEM str_eeprom_list_list[] = "list";
2232 const parse_token_string_t PROGMEM cmd_eeprom_list_action =
2233         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_list_result, action,
2234                                  str_eeprom_list_list);
2235
2236 const char PROGMEM help_eeprom_list[] = "list all eeprom init commands";
2237 const parse_inst_t PROGMEM cmd_eeprom_list = {
2238         .f = cmd_eeprom_list_parsed,  /* function to call */
2239         .data = NULL,      /* 2nd arg of func */
2240         .help_str = help_eeprom_list,
2241         .tokens = {        /* token list, NULL terminated */
2242                 (PGM_P)&cmd_eeprom_list_cmd,
2243                 (PGM_P)&cmd_eeprom_list_action,
2244                 NULL,
2245         },
2246 };
2247
2248
2249 /* ************* */
2250
2251 struct cmd_dump_i2c_result {
2252         fixed_string_t cmd;
2253 };
2254
2255 static void cmd_dump_i2c_parsed(void *parsed_result, void *data)
2256 {
2257         struct i2c_ans_imuboard_status imu;
2258         uint8_t irq_flags;
2259
2260         (void)parsed_result;
2261         (void)data;
2262
2263         while (!cmdline_keypressed()) {
2264                 IRQ_LOCK(irq_flags);
2265                 memcpy(&imu, &imuboard_status, sizeof(imu));
2266                 IRQ_UNLOCK(irq_flags);
2267
2268                 if (imu.flags & IMUBOARD_STATUS_GPS_OK) {
2269                         printf_P(PSTR("GPS lat=%"PRIi32" long=%"PRIi32
2270                                         " alt=%"PRIi32"\n"),
2271                                 imu.latitude, imu.longitude, imu.altitude);
2272                 }
2273                 else
2274                         printf_P(PSTR("GPS unavailable"));
2275                 i2c_protocol_debug();
2276                 wait_ms(100);
2277         }
2278 }
2279
2280 const char PROGMEM str_dump_i2c[] = "dump_i2c";
2281 const parse_token_string_t PROGMEM cmd_dump_i2c_cmd =
2282         TOKEN_STRING_INITIALIZER(struct cmd_dump_i2c_result, cmd,
2283                                  str_dump_i2c);
2284
2285 const char PROGMEM help_dump_i2c[] = "dump_i2c";
2286 const parse_inst_t PROGMEM cmd_dump_i2c = {
2287         .f = cmd_dump_i2c_parsed,  /* function to call */
2288         .data = NULL,      /* 2nd arg of func */
2289         .help_str = help_dump_i2c,
2290         .tokens = {        /* token list, NULL terminated */
2291                 (PGM_P)&cmd_dump_i2c_cmd,
2292                 NULL,
2293         },
2294 };
2295
2296
2297 /* ************* */
2298
2299 /* in progmem */
2300 const parse_ctx_t PROGMEM main_ctx[] = {
2301
2302         /* commands_gen.c */
2303         &cmd_reset,
2304         &cmd_bootloader,
2305         &cmd_log,
2306         &cmd_log_show,
2307         &cmd_log_type,
2308         &cmd_stack_space,
2309         &cmd_callout,
2310         &cmd_help,
2311         &cmd_neigh_del,
2312         &cmd_neigh_add,
2313         &cmd_neigh_list,
2314         &cmd_read,
2315         &cmd_write_none,
2316         &cmd_write_u8,
2317         &cmd_write_u16,
2318         &cmd_write_u32,
2319         &cmd_sendmsg,
2320         &cmd_sendmsg_name,
2321         &cmd_range,
2322         &cmd_range_period,
2323         &cmd_range_count,
2324         &cmd_range_powermask,
2325         &cmd_range_dstaddr,
2326         &cmd_monitor,
2327         &cmd_monitor_period,
2328         &cmd_monitor_add,
2329         &cmd_monitor_del,
2330         &cmd_ping,
2331         &cmd_raw,
2332         &cmd_baudrate,
2333         &cmd_beep,
2334         &cmd_servo_set,
2335         &cmd_servo_bypassppm,
2336         &cmd_servo_show,
2337         &cmd_test_spi,
2338         &cmd_dump_xbee_stats,
2339         &cmd_rc_proto_stats,
2340         &cmd_rc_proto_timers,
2341         &cmd_rc_proto_timers_show,
2342         &cmd_rc_proto_mode,
2343         &cmd_rc_proto_mode2,
2344         &cmd_rc_proto_mode3,
2345         &cmd_rc_proto_hello,
2346         &cmd_rc_proto_hello_name,
2347         &cmd_rc_proto_echo,
2348         &cmd_rc_proto_echo_name,
2349         &cmd_test_eeprom_config,
2350         &cmd_eeprom_del,
2351         &cmd_eeprom_add,
2352         &cmd_eeprom_add2,
2353         &cmd_eeprom_list,
2354         &cmd_dump_i2c,
2355         NULL,
2356 };