display xbee result in decimal
[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
40 #include "callout.h"
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 "main.h"
48 #include "cmdline.h"
49 #include "beep.h"
50 #include "eeprom_config.h"
51
52 /* commands_gen.c */
53 extern const parse_inst_t PROGMEM cmd_reset;
54 extern const parse_inst_t PROGMEM cmd_bootloader;
55 extern const parse_inst_t PROGMEM cmd_log;
56 extern const parse_inst_t PROGMEM cmd_log_show;
57 extern const parse_inst_t PROGMEM cmd_log_type;
58 extern const parse_inst_t PROGMEM cmd_stack_space;
59 extern const parse_inst_t PROGMEM cmd_scheduler;
60
61 static int monitor_period_ms = 1000;
62 static int monitor_running = 0;
63 static int monitor_count = 0;
64 static struct callout monitor_event;
65 struct monitor_reg *monitor_current;
66
67 static int range_period_ms = 1000;
68 static int range_powermask = 0x1F;
69 //static uint8_t range_power = 0;
70 static int range_running = 0;
71 static uint64_t range_dstaddr = 0xFFFF; /* broadcast by default */
72 static struct callout range_event;
73 static int range_count = 100;
74 static int range_cur_count = 0;
75
76 static void monitor_cb(struct callout_manager *cm,
77                        struct callout *clt, void *dummy)
78 {
79         (void)clt;
80         (void)dummy;
81
82         if (monitor_current == NULL)
83                 monitor_current = LIST_FIRST(&xbee_monitor_list);
84
85         xbeeapp_send_atcmd(monitor_current->atcmd, NULL, 0, 0, NULL, NULL);
86         monitor_current = LIST_NEXT(monitor_current, next);
87         callout_reset(cm, &monitor_event,
88                       monitor_period_ms / monitor_count,
89                       SINGLE, monitor_cb, NULL);
90 }
91
92 static void range_cb(struct callout_manager *cm,
93                      struct callout *clt, void *dummy)
94 {
95         (void)cm;
96         (void)clt;
97         (void)dummy;
98 #if 0
99         uint8_t i, mask;
100         struct rc_proto_range rangepkt;
101
102         (void)clt;
103         (void)dummy;
104
105         range_cur_count--;
106
107         /* get new xmit power */
108         for (i = 1; i <= 8; i++) {
109                 mask = 1 << ((range_power + i) & 0x7);
110                 if (mask & range_powermask)
111                         break;
112         }
113         range_power = ((range_power + i) & 0x7);
114
115         xbeeapp_send_atcmd("PL", &range_power, sizeof(range_power), 0, NULL, NULL);
116
117         rangepkt.type = RC_PROTO_TYPE_RANGE;
118         rangepkt.power_level = range_power;
119
120         xbeeapp_send_msg(range_dstaddr, &rangepkt, sizeof(rangepkt), 0);
121
122         if (range_cur_count == 0) {
123                 range_running = 0;
124                 return;
125         }
126
127         callout_reset(cm, &range_event,
128                       range_period_ms,
129                       SINGLE, range_cb, NULL);
130 #endif
131 }
132
133 /* this structure is filled when cmd_help is parsed successfully */
134 struct cmd_help_result {
135         fixed_string_t help;
136         struct xbee_atcmd *cmd;
137 };
138
139 /* function called when cmd_help is parsed successfully */
140 static void cmd_help_parsed(void *parsed_result, void *data)
141 {
142         struct cmd_help_result *res = parsed_result;
143         struct xbee_atcmd cmdcopy;
144         int type;
145
146         (void)data;
147
148         memcpy_P(&cmdcopy, res->cmd, sizeof(cmdcopy));
149         type = (cmdcopy.flags & (XBEE_ATCMD_F_READ | XBEE_ATCMD_F_WRITE));
150         switch (type) {
151                 case XBEE_ATCMD_F_READ:
152                         printf_P(PSTR("Read-only\r\n"));
153                         break;
154                 case XBEE_ATCMD_F_WRITE:
155                         printf_P(PSTR("Write-only\r\n"));
156                         break;
157                 default:
158                         printf_P(PSTR("Read-write\r\n"));
159                         break;
160         }
161         if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_NONE)
162                 printf_P(PSTR("No argument\r\n"));
163         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_U8)
164                 printf_P(PSTR("Register is unsigned 8 bits\r\n"));
165         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_U16)
166                 printf_P(PSTR("Register is unsigned 16 bits\r\n"));
167         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_U32)
168                 printf_P(PSTR("Register is unsigned 32 bits\r\n"));
169         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_S16)
170                 printf_P(PSTR("Register is signed 16 bits\r\n"));
171         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_STRING_20B)
172                 printf_P(PSTR("Register is a 20 bytes string\r\n"));
173         else
174                 printf_P(PSTR("Unknown argument\r\n"));
175
176         printf_P(PSTR("%S\r\n"), cmdcopy.help);
177 }
178 const char PROGMEM str_help_help[] = "help";
179
180 const parse_token_string_t PROGMEM cmd_help_help =
181         TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, str_help_help);
182
183 const parse_token_atcmd_t PROGMEM cmd_help_atcmd =
184         TOKEN_ATCMD_INITIALIZER(struct cmd_help_result, cmd, &xbee_dev,
185                                 0, 0);
186
187 const char PROGMEM help_help[] = "Help a register using an AT command";
188 const parse_inst_t PROGMEM cmd_help = {
189         .f = cmd_help_parsed,  /* function to call */
190         .data = NULL,      /* 2nd arg of func */
191         .help_str = help_help,
192         .tokens = {        /* token list, NULL terminated */
193                 (PGM_P)&cmd_help_help,
194                 (PGM_P)&cmd_help_atcmd,
195                 NULL,
196         },
197 };
198
199 /* ************* */
200
201 struct cmd_neigh_del_result {
202         fixed_string_t cmd;
203         fixed_string_t action;
204         struct xbee_neigh *neigh;
205 };
206
207 static void cmd_neigh_del_parsed(void *parsed_result,
208                                 void *data)
209 {
210         struct cmd_neigh_del_result *res = parsed_result;
211
212         (void)data;
213         xbee_neigh_del(xbee_dev, res->neigh);
214 }
215
216 const char PROGMEM str_neigh_del_neigh[] = "neigh";
217 const parse_token_string_t PROGMEM cmd_neigh_del_cmd =
218         TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, cmd,
219                                  str_neigh_del_neigh);
220 const char PROGMEM str_neigh_del_del[] = "del";
221 const parse_token_string_t PROGMEM cmd_neigh_del_action =
222         TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, action,
223                                  str_neigh_del_del);
224 const parse_token_neighbor_t PROGMEM cmd_neigh_del_neigh =
225         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_neigh_del_result, neigh,
226                                    &xbee_dev);
227
228 const char PROGMEM help_neigh_del[] = "delete a neighbor";
229 const parse_inst_t PROGMEM cmd_neigh_del = {
230         .f = cmd_neigh_del_parsed,  /* function to call */
231         .data = NULL,      /* 2nd arg of func */
232         .help_str = help_neigh_del,
233         .tokens = {        /* token list, NULL terminated */
234                 (PGM_P)&cmd_neigh_del_cmd,
235                 (PGM_P)&cmd_neigh_del_action,
236                 (PGM_P)&cmd_neigh_del_neigh,
237                 NULL,
238         },
239 };
240
241 /* ************* */
242
243 struct cmd_neigh_add_result {
244         fixed_string_t cmd;
245         fixed_string_t action;
246         fixed_string_t name;
247         uint64_t addr;
248 };
249
250 static void cmd_neigh_add_parsed(void *parsed_result,
251                                  void *data)
252 {
253         struct cmd_neigh_add_result *res = parsed_result;
254
255         (void)data;
256         if (xbee_neigh_add(xbee_dev, res->name, res->addr) == NULL)
257                 printf_P(PSTR("name or addr already exist\r\n"));
258 }
259
260 const char PROGMEM str_neigh_add_neigh[] = "neigh";
261 const parse_token_string_t PROGMEM cmd_neigh_add_cmd =
262         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, cmd,
263                                  str_neigh_add_neigh);
264 const char PROGMEM str_neigh_add_add[] = "add";
265 const parse_token_string_t PROGMEM cmd_neigh_add_action =
266         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, action,
267                                  str_neigh_add_add);
268 const parse_token_string_t PROGMEM cmd_neigh_add_name =
269         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, name, NULL);
270 const parse_token_num_t PROGMEM cmd_neigh_add_addr =
271         TOKEN_NUM_INITIALIZER(struct cmd_neigh_add_result, addr, UINT64);
272
273 const char PROGMEM help_neigh_add[] = "add a neighbor";
274 const parse_inst_t PROGMEM cmd_neigh_add = {
275         .f = cmd_neigh_add_parsed,  /* function to call */
276         .data = NULL,      /* 2nd arg of func */
277         .help_str = help_neigh_add,
278         .tokens = {        /* token list, NULL terminated */
279                 (PGM_P)&cmd_neigh_add_cmd,
280                 (PGM_P)&cmd_neigh_add_action,
281                 (PGM_P)&cmd_neigh_add_name,
282                 (PGM_P)&cmd_neigh_add_addr,
283                 NULL,
284         },
285 };
286
287 /* ************* */
288
289 struct cmd_neigh_list_result {
290         fixed_string_t cmd;
291         fixed_string_t action;
292 };
293
294 static void cmd_neigh_list_parsed(void *parsed_result,
295                                 void *data)
296 {
297         struct xbee_neigh *neigh;
298
299         (void)parsed_result;
300         (void)data;
301         LIST_FOREACH(neigh, &xbee_dev->neigh_list, next) {
302                 printf_P(PSTR(" %s: 0x%.8"PRIx32"%.8"PRIx32"\r\n"),
303                          neigh->name,
304                          (uint32_t)(neigh->addr >> 32ULL),
305                          (uint32_t)(neigh->addr & 0xFFFFFFFF));
306         }
307 }
308
309 const char PROGMEM str_neigh_list_neigh[] = "neigh";
310 const parse_token_string_t PROGMEM cmd_neigh_list_cmd =
311         TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, cmd,
312                                  str_neigh_list_neigh);
313 const char PROGMEM str_neigh_list_list[] = "list";
314 const parse_token_string_t PROGMEM cmd_neigh_list_action =
315         TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, action,
316                                  str_neigh_list_list);
317
318 const char PROGMEM help_neigh_list[] = "list all knwon neighbors";
319 const parse_inst_t PROGMEM cmd_neigh_list = {
320         .f = cmd_neigh_list_parsed,  /* function to call */
321         .data = NULL,      /* 2nd arg of func */
322         .help_str = help_neigh_list,
323         .tokens = {        /* token list, NULL terminated */
324                 (PGM_P)&cmd_neigh_list_cmd,
325                 (PGM_P)&cmd_neigh_list_action,
326                 NULL,
327         },
328 };
329
330
331
332
333 /* ************* */
334
335 /* this structure is filled when cmd_read is parsed successfully */
336 struct cmd_read_result {
337         fixed_string_t read;
338         struct xbee_atcmd *cmd;
339 };
340
341 /* function called when cmd_read is parsed successfully */
342 static void cmd_read_parsed(void *parsed_result,
343                             void *data)
344 {
345         struct cmd_read_result *res = parsed_result;
346         struct xbee_atcmd copy;
347         char cmd[3];
348
349         (void)data;
350         memcpy_P(&copy, res->cmd, sizeof(copy));
351         memcpy_P(&cmd, copy.name, 2);
352         cmd[2] = '\0';
353         xbeeapp_send_atcmd(cmd, NULL, 0, 1, NULL, NULL);
354 }
355
356 const char PROGMEM str_read_read[] = "read";
357
358 const parse_token_string_t PROGMEM cmd_read_read =
359         TOKEN_STRING_INITIALIZER(struct cmd_read_result, read,
360                                  str_read_read);
361
362 const parse_token_atcmd_t PROGMEM cmd_read_atcmd =
363         TOKEN_ATCMD_INITIALIZER(struct cmd_read_result, cmd, &xbee_dev,
364                                 XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ);
365
366 const char PROGMEM help_read[] = "Read a register using an AT command";
367 const parse_inst_t PROGMEM cmd_read = {
368         .f = cmd_read_parsed,  /* function to call */
369         .data = NULL,      /* 2nd arg of func */
370         .help_str = help_read,
371         .tokens = {        /* token list, NULL terminated */
372                 (PGM_P)&cmd_read_read,
373                 (PGM_P)&cmd_read_atcmd,
374                 NULL,
375         },
376 };
377
378
379 /* ************* */
380
381 /* this structure is filled when cmd_write is parsed successfully */
382 struct cmd_write_result {
383         fixed_string_t write;
384         struct xbee_atcmd *cmd;
385         union {
386                 uint8_t u8;
387                 uint16_t u16;
388                 uint32_t u32;
389         };
390 };
391
392 /* function called when cmd_write is parsed successfully */
393 static void cmd_write_parsed(void *parsed_result, void *data)
394 {
395         struct cmd_write_result *res = parsed_result;
396         struct xbee_atcmd copy;
397         char cmd[3];
398         int len;
399         void *param;
400
401         (void)data;
402         memcpy_P(&copy, res->cmd, sizeof(copy));
403
404         if (copy.flags & XBEE_ATCMD_F_PARAM_NONE) {
405                 len = 0;
406                 param = NULL;
407         }
408         else if (copy.flags & XBEE_ATCMD_F_PARAM_U8) {
409                 len = sizeof(res->u8);
410                 param = &res->u8;
411         }
412         else if (copy.flags & XBEE_ATCMD_F_PARAM_U16) {
413                 len = sizeof(res->u16);
414                 res->u16 = htons(res->u16);
415                 param = &res->u16;
416         }
417         else if (copy.flags & XBEE_ATCMD_F_PARAM_U32) {
418                 len = sizeof(res->u32);
419                 res->u32 = htonl(res->u32);
420                 param = &res->u32;
421         }
422         else {
423                 printf_P(PSTR("Unknown argument type\r\n"));
424                 return;
425         }
426         memcpy_P(&cmd, copy.name, 2);
427         cmd[2] = '\0';
428         xbeeapp_send_atcmd(cmd, param, len, 1, NULL, NULL);
429 }
430
431 const char PROGMEM str_write_none[] = "write";
432
433 const parse_token_string_t PROGMEM cmd_write_write =
434         TOKEN_STRING_INITIALIZER(struct cmd_write_result, write,
435                                  str_write_none);
436
437 const parse_token_atcmd_t PROGMEM cmd_write_none_atcmd =
438         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
439                                 &xbee_dev,
440                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE,
441                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE);
442
443 const char PROGMEM help_write_none[] = "Send an AT command (no argument)";
444
445 const parse_inst_t PROGMEM cmd_write_none = {
446         .f = cmd_write_parsed,  /* function to call */
447         .data = NULL,      /* 2nd arg of func */
448         .help_str = help_write_none,
449         .tokens = {        /* token list, NULL terminated */
450                 (PGM_P)&cmd_write_write,
451                 (PGM_P)&cmd_write_none_atcmd,
452                 NULL,
453         },
454 };
455
456 const parse_token_atcmd_t PROGMEM cmd_write_u8_atcmd =
457         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
458                                 &xbee_dev,
459                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8,
460                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8);
461
462 const parse_token_num_t PROGMEM cmd_write_u8_u8 =
463         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u8, UINT8);
464
465 const char PROGMEM help_write_u8[] = "Write a 8 bits register using an AT command";
466
467 const parse_inst_t PROGMEM cmd_write_u8 = {
468         .f = cmd_write_parsed,  /* function to call */
469         .data = NULL,      /* 2nd arg of func */
470         .help_str = help_write_u8,
471         .tokens = {        /* token list, NULL terminated */
472                 (PGM_P)&cmd_write_write,
473                 (PGM_P)&cmd_write_u8_atcmd,
474                 (PGM_P)&cmd_write_u8_u8,
475                 NULL,
476         },
477 };
478
479 const parse_token_atcmd_t PROGMEM cmd_write_u16_atcmd =
480         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
481                                 &xbee_dev,
482                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16,
483                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16);
484
485 const parse_token_num_t PROGMEM cmd_write_u16_u16 =
486         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u16, UINT16);
487
488 const char PROGMEM help_write_u16[] = "Write a 16 bits register using an AT command";
489
490 const parse_inst_t PROGMEM cmd_write_u16 = {
491         .f = cmd_write_parsed,  /* function to call */
492         .data = NULL,      /* 2nd arg of func */
493         .help_str = help_write_u16,
494         .tokens = {        /* token list, NULL terminated */
495                 (PGM_P)&cmd_write_write,
496                 (PGM_P)&cmd_write_u16_atcmd,
497                 (PGM_P)&cmd_write_u16_u16,
498                 NULL,
499         },
500 };
501
502 const parse_token_atcmd_t PROGMEM cmd_write_u32_atcmd =
503         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
504                                 &xbee_dev,
505                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32,
506                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32);
507
508 const parse_token_num_t PROGMEM cmd_write_u32_u32 =
509         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u32, UINT32);
510
511 const char PROGMEM help_write_u32[] = "Write a 32 bits register using an AT command";
512
513 const parse_inst_t PROGMEM cmd_write_u32 = {
514         .f = cmd_write_parsed,  /* function to call */
515         .data = NULL,      /* 2nd arg of func */
516         .help_str = help_write_u32,
517         .tokens = {        /* token list, NULL terminated */
518                 (PGM_P)&cmd_write_write,
519                 (PGM_P)&cmd_write_u32_atcmd,
520                 (PGM_P)&cmd_write_u32_u32,
521                 NULL,
522         },
523 };
524
525
526 /* ************* */
527
528 /* this structure is filled when cmd_sendmsg is parsed successfully */
529 struct cmd_sendmsg_result {
530         fixed_string_t sendmsg;
531         uint64_t addr;
532         fixed_string_t data;
533 };
534
535 /* function called when cmd_sendmsg is parsed successfully */
536 static void cmd_sendmsg_parsed(void *parsed_result, void *data)
537 {
538         struct cmd_sendmsg_result *res = parsed_result;
539
540         (void)data;
541         xbeeapp_send_msg(res->addr, res->data, strlen(res->data), 1);
542 }
543
544 const char PROGMEM str_sendmsg[] = "sendmsg";
545
546 const parse_token_string_t PROGMEM cmd_sendmsg_sendmsg =
547         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, sendmsg,
548                                  str_sendmsg);
549
550 const parse_token_num_t PROGMEM cmd_sendmsg_addr =
551         TOKEN_NUM_INITIALIZER(struct cmd_sendmsg_result, addr, UINT64);
552
553 const parse_token_string_t PROGMEM cmd_sendmsg_data =
554         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, data, NULL);
555
556 const char PROGMEM help_sendmsg[] = "Send data to a node using its address";
557
558 const parse_inst_t PROGMEM cmd_sendmsg = {
559         .f = cmd_sendmsg_parsed,  /* function to call */
560         .data = NULL,      /* 2nd arg of func */
561         .help_str = help_sendmsg,
562         .tokens = {        /* token list, NULL terminated */
563                 (PGM_P)&cmd_sendmsg_sendmsg,
564                 (PGM_P)&cmd_sendmsg_addr,
565                 (PGM_P)&cmd_sendmsg_data,
566                 NULL,
567         },
568 };
569
570 /* ************* */
571
572 /* this structure is filled when cmd_sendmsg_name is parsed successfully */
573 struct cmd_sendmsg_name_result {
574         fixed_string_t sendmsg_name;
575         struct xbee_neigh *neigh;
576         fixed_string_t data;
577 };
578
579 /* function called when cmd_sendmsg_name is parsed successfully */
580 static void cmd_sendmsg_name_parsed(void *parsed_result, void *data)
581 {
582         struct cmd_sendmsg_name_result *res = parsed_result;
583
584         (void)data;
585         xbeeapp_send_msg(res->neigh->addr, res->data, strlen(res->data), 1);
586 }
587
588 const parse_token_string_t PROGMEM cmd_sendmsg_name_sendmsg_name =
589         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, sendmsg_name,
590                                  str_sendmsg);
591
592 const parse_token_neighbor_t PROGMEM cmd_sendmsg_name_neigh =
593         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_sendmsg_name_result, neigh,
594                                    &xbee_dev);
595
596 const parse_token_string_t PROGMEM cmd_sendmsg_name_data =
597         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, data, NULL);
598
599 const char PROGMEM help_sendmsg_name[] = "Send data to a node using its name";
600
601 const parse_inst_t PROGMEM cmd_sendmsg_name = {
602         .f = cmd_sendmsg_name_parsed,  /* function to call */
603         .data = NULL,      /* 2nd arg of func */
604         .help_str = help_sendmsg_name,
605         .tokens = {        /* token list, NULL terminated */
606                 (PGM_P)&cmd_sendmsg_name_sendmsg_name,
607                 (PGM_P)&cmd_sendmsg_name_neigh,
608                 (PGM_P)&cmd_sendmsg_name_data,
609                 NULL,
610         },
611 };
612
613
614 /* ************* */
615
616 /* this structure is filled when cmd_range is parsed successfully */
617 struct cmd_range_result {
618         fixed_string_t range;
619         fixed_string_t action;
620 };
621
622 /* function called when cmd_range is parsed successfully */
623 static void cmd_range_parsed(void *parsed_result, void *data)
624 {
625         struct cmd_range_result *res = parsed_result;
626
627         (void)data;
628         if (!strcmp_P(res->action, PSTR("show"))) {
629                 printf_P(PSTR("range infos:\r\n"));
630                 printf_P(PSTR("  range period %d\r\n"), range_period_ms);
631                 printf_P(PSTR("  range count %d\r\n"), range_count);
632                 printf_P(PSTR("  range powermask 0x%x\r\n"), range_powermask);
633                 printf_P(PSTR("  range dstaddr 0x%.8"PRIx32"%.8"PRIx32"\r\n"),
634                          (uint32_t)(range_dstaddr >> 32ULL),
635                          (uint32_t)(range_dstaddr & 0xFFFFFFFF));
636
637                 if (range_running)
638                         printf_P(PSTR("  range test is running\r\n"));
639                 else
640                         printf_P(PSTR("  range test is not running\r\n"));
641         }
642         else if (!strcmp(res->action, "start")) {
643                 if (range_running) {
644                         printf_P(PSTR("already running\r\n"));
645                         return;
646                 }
647                 range_cur_count = range_count;
648                 callout_init(&range_event);
649                 callout_reset(&cm, &range_event, 0,
650                               SINGLE, range_cb, NULL);
651                 range_running = 1;
652         }
653         else if (!strcmp(res->action, "end")) {
654                 if (range_running == 0) {
655                         printf_P(PSTR("not running\r\n"));
656                         return;
657                 }
658                 range_running = 0;
659                 callout_stop(&cm, &range_event);
660         }
661 }
662
663 const char PROGMEM str_range[] = "range";
664 const char PROGMEM str_range_tokens[] = "show#start#end";
665
666 const parse_token_string_t PROGMEM cmd_range_range =
667         TOKEN_STRING_INITIALIZER(struct cmd_range_result, range,
668                                  str_range);
669 const parse_token_string_t PROGMEM cmd_range_action =
670         TOKEN_STRING_INITIALIZER(struct cmd_range_result, action,
671                                  str_range_tokens);
672
673 const char PROGMEM help_range[] = "start/stop/show current rangeing";
674
675 const parse_inst_t PROGMEM cmd_range = {
676         .f = cmd_range_parsed,  /* function to call */
677         .data = NULL,      /* 2nd arg of func */
678         .help_str = help_range,
679         .tokens = {        /* token list, NULL terminated */
680                 (PGM_P)&cmd_range_range,
681                 (PGM_P)&cmd_range_action,
682                 NULL,
683         },
684 };
685
686 /* ************* */
687
688 /* this structure is filled when cmd_range_period is parsed successfully */
689 struct cmd_range_period_result {
690         fixed_string_t range;
691         fixed_string_t action;
692         uint32_t period;
693 };
694
695 /* function called when cmd_range_period is parsed successfully */
696 static void cmd_range_period_parsed(void *parsed_result, void *data)
697 {
698         struct cmd_range_period_result *res = parsed_result;
699
700         (void)data;
701         if (res->period < 10) {
702                 printf_P(PSTR("error, minimum period is 10 ms\r\n"));
703                 return;
704         }
705
706         range_period_ms = res->period;
707 }
708
709 const char PROGMEM str_period[] = "period";
710
711 const parse_token_string_t PROGMEM cmd_range_period_range_period =
712         TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, range,
713                                  str_range);
714 const parse_token_string_t PROGMEM cmd_range_period_action =
715         TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, action,
716                                  str_period);
717 const parse_token_num_t PROGMEM cmd_range_period_period =
718         TOKEN_NUM_INITIALIZER(struct cmd_range_period_result, period, UINT32);
719
720 const char PROGMEM help_range_period[] = "set range test period";
721
722 const parse_inst_t PROGMEM cmd_range_period = {
723         .f = cmd_range_period_parsed,  /* function to call */
724         .data = NULL,      /* 2nd arg of func */
725         .help_str = help_range_period,
726         .tokens = {        /* token list, NULL terminated */
727                 (PGM_P)&cmd_range_period_range_period,
728                 (PGM_P)&cmd_range_period_action,
729                 (PGM_P)&cmd_range_period_period,
730                 NULL,
731         },
732 };
733
734 /* ************* */
735
736 /* this structure is filled when cmd_range_count is parsed successfully */
737 struct cmd_range_count_result {
738         fixed_string_t range;
739         fixed_string_t action;
740         uint32_t count;
741 };
742
743 /* function called when cmd_range_count is parsed successfully */
744 static void cmd_range_count_parsed(void *parsed_result, void *data)
745 {
746         struct cmd_range_count_result *res = parsed_result;
747
748         (void)data;
749         range_count = res->count;
750 }
751
752 const char PROGMEM str_count[] = "count";
753
754 const parse_token_string_t PROGMEM cmd_range_count_range_count =
755         TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, range,
756                                  str_range);
757 const parse_token_string_t PROGMEM cmd_range_count_action =
758         TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, action,
759                                  str_count);
760 const parse_token_num_t PROGMEM cmd_range_count_count =
761         TOKEN_NUM_INITIALIZER(struct cmd_range_count_result, count, UINT32);
762
763
764 const char PROGMEM help_range_count[] = "set range test count";
765
766 const parse_inst_t PROGMEM cmd_range_count = {
767         .f = cmd_range_count_parsed,  /* function to call */
768         .data = NULL,      /* 2nd arg of func */
769         .help_str = help_range_count,
770         .tokens = {        /* token list, NULL terminated */
771                 (PGM_P)&cmd_range_count_range_count,
772                 (PGM_P)&cmd_range_count_action,
773                 (PGM_P)&cmd_range_count_count,
774                 NULL,
775         },
776 };
777
778 /* ************* */
779
780 /* this structure is filled when cmd_range_powermask is parsed successfully */
781 struct cmd_range_powermask_result {
782         fixed_string_t range;
783         fixed_string_t action;
784         uint8_t powermask;
785 };
786
787 /* function called when cmd_range_powermask is parsed successfully */
788 static void cmd_range_powermask_parsed(void *parsed_result, void *data)
789 {
790         struct cmd_range_powermask_result *res = parsed_result;
791
792         (void)data;
793         range_powermask = res->powermask;
794 }
795
796 const char PROGMEM str_powermask[] = "powermask";
797
798 const parse_token_string_t PROGMEM cmd_range_powermask_range_powermask =
799         TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, range,
800                                  str_range);
801 const parse_token_string_t PROGMEM cmd_range_powermask_action =
802         TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, action,
803                                  str_powermask);
804 const parse_token_num_t PROGMEM cmd_range_powermask_powermask =
805         TOKEN_NUM_INITIALIZER(struct cmd_range_powermask_result, powermask,
806                               UINT8);
807
808
809 const char PROGMEM help_range_powermask[] = "set range test powermask";
810
811 const parse_inst_t PROGMEM cmd_range_powermask = {
812         .f = cmd_range_powermask_parsed,  /* function to call */
813         .data = NULL,      /* 2nd arg of func */
814         .help_str = help_range_powermask,
815         .tokens = {        /* token list, NULL terminated */
816                 (PGM_P)&cmd_range_powermask_range_powermask,
817                 (PGM_P)&cmd_range_powermask_action,
818                 (PGM_P)&cmd_range_powermask_powermask,
819                 NULL,
820         },
821 };
822
823 /* ************* */
824
825 /* this structure is filled when cmd_range_dstaddr is parsed successfully */
826 struct cmd_range_dstaddr_result {
827         fixed_string_t range;
828         fixed_string_t action;
829         uint64_t dstaddr;
830 };
831
832 /* function called when cmd_range_dstaddr is parsed successfully */
833 static void cmd_range_dstaddr_parsed(void *parsed_result, void *data)
834 {
835         struct cmd_range_dstaddr_result *res = parsed_result;
836
837         (void)data;
838         range_dstaddr = res->dstaddr;
839 }
840
841 const char PROGMEM str_dstaddr[] = "dstaddr";
842
843 const parse_token_string_t PROGMEM cmd_range_dstaddr_range_dstaddr =
844         TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, range,
845                                  str_range);
846 const parse_token_string_t PROGMEM cmd_range_dstaddr_action =
847         TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, action,
848                                  str_dstaddr);
849 const parse_token_num_t PROGMEM cmd_range_dstaddr_dstaddr =
850         TOKEN_NUM_INITIALIZER(struct cmd_range_dstaddr_result, dstaddr, UINT64);
851
852
853 const char PROGMEM help_range_dstaddr[] = "set register rangeing dstaddr";
854
855 const parse_inst_t PROGMEM cmd_range_dstaddr = {
856         .f = cmd_range_dstaddr_parsed,  /* function to call */
857         .data = NULL,      /* 2nd arg of func */
858         .help_str = help_range_dstaddr,
859         .tokens = {        /* token list, NULL terminated */
860                 (PGM_P)&cmd_range_dstaddr_range_dstaddr,
861                 (PGM_P)&cmd_range_dstaddr_action,
862                 (PGM_P)&cmd_range_dstaddr_dstaddr,
863                 NULL,
864         },
865 };
866
867
868 /* ************* */
869
870 /* this structure is filled when cmd_monitor is parsed successfully */
871 struct cmd_monitor_result {
872         fixed_string_t monitor;
873         fixed_string_t action;
874 };
875
876 /* function called when cmd_monitor is parsed successfully */
877 static void cmd_monitor_parsed(void *parsed_result, void *data)
878 {
879         struct cmd_monitor_result *res = parsed_result;
880         struct monitor_reg *m;
881
882         (void)data;
883         if (!strcmp_P(res->action, PSTR("show"))) {
884                 printf_P(PSTR("monitor period is %d ms, %d regs in list\r\n"),
885                        monitor_period_ms, monitor_count);
886                 LIST_FOREACH(m, &xbee_monitor_list, next)
887                         printf_P(PSTR(" %S\r\n"), m->desc);
888         }
889         else if (!strcmp_P(res->action, PSTR("start"))) {
890                 if (monitor_running) {
891                         printf_P(PSTR("already running\r\n"));
892                         return;
893                 }
894                 if (monitor_count == 0) {
895                         printf_P(PSTR("no regs to be monitored\r\n"));
896                         return;
897                 }
898                 callout_init(&monitor_event);
899                 callout_reset(&cm, &monitor_event, 0, SINGLE, monitor_cb, NULL);
900                 monitor_running = 1;
901                 monitor_current = LIST_FIRST(&xbee_monitor_list);
902                 printf_P(PSTR("monitor cb: %S %s\r\n"),
903                          monitor_current->desc,
904                          monitor_current->atcmd);
905
906         }
907         else if (!strcmp_P(res->action, PSTR("end"))) {
908                 if (monitor_running == 0) {
909                         printf_P(PSTR("not running\r\n"));
910                         return;
911                 }
912                 monitor_running = 0;
913                 callout_stop(&cm, &monitor_event);
914         }
915 }
916
917 const char PROGMEM str_monitor[] = "monitor";
918 const char PROGMEM str_monitor_tokens[] = "show#start#end";
919
920 const parse_token_string_t PROGMEM cmd_monitor_monitor =
921         TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, monitor,
922                                  str_monitor);
923 const parse_token_string_t PROGMEM cmd_monitor_action =
924         TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, action,
925                                  str_monitor_tokens);
926
927 const char PROGMEM help_monitor[] = "start/stop/show current monitoring";
928
929 const parse_inst_t PROGMEM cmd_monitor = {
930         .f = cmd_monitor_parsed,  /* function to call */
931         .data = NULL,      /* 2nd arg of func */
932         .help_str = help_monitor,
933         .tokens = {        /* token list, NULL terminated */
934                 (PGM_P)&cmd_monitor_monitor,
935                 (PGM_P)&cmd_monitor_action,
936                 NULL,
937         },
938 };
939
940 /* ************* */
941
942 /* this structure is filled when cmd_monitor_add is parsed successfully */
943 struct cmd_monitor_add_result {
944         fixed_string_t monitor;
945         fixed_string_t action;
946         struct xbee_atcmd *cmd;
947 };
948
949 /* function called when cmd_monitor_add is parsed successfully */
950 static void cmd_monitor_add_parsed(void *parsed_result, void *data)
951 {
952         struct cmd_monitor_add_result *res = parsed_result;
953         struct monitor_reg *m;
954         struct xbee_atcmd copy;
955
956         (void)data;
957         memcpy_P(&copy, res->cmd, sizeof(copy));
958         LIST_FOREACH(m, &xbee_monitor_list, next) {
959                 if (!strcmp_P(m->atcmd, copy.name))
960                         break;
961         }
962
963         if (m != NULL) {
964                 printf_P(PSTR("already exist\r\n"));
965                 return;
966         }
967
968         m = malloc(sizeof(*m));
969         if (m == NULL) {
970                 printf_P(PSTR("no mem\r\n"));
971                 return;
972         }
973         m->desc = copy.desc;
974         strcpy_P(m->atcmd, copy.name);
975         LIST_INSERT_HEAD(&xbee_monitor_list, m, next);
976         monitor_count ++;
977 }
978
979 const char PROGMEM str_monitor_add[] = "add";
980
981 const parse_token_string_t PROGMEM cmd_monitor_add_monitor_add =
982         TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, monitor,
983                                  str_monitor);
984 const parse_token_string_t PROGMEM cmd_monitor_add_action =
985         TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, action,
986                                  str_monitor_add);
987 const parse_token_atcmd_t PROGMEM cmd_monitor_add_atcmd =
988         TOKEN_ATCMD_INITIALIZER(struct cmd_monitor_add_result, cmd, &xbee_dev,
989                                 XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ);
990
991
992 const char PROGMEM help_monitor_add[] = "add a register in monitor list";
993
994 const parse_inst_t PROGMEM cmd_monitor_add = {
995         .f = cmd_monitor_add_parsed,  /* function to call */
996         .data = NULL,      /* 2nd arg of func */
997         .help_str = help_monitor_add,
998         .tokens = {        /* token list, NULL terminated */
999                 (PGM_P)&cmd_monitor_add_monitor_add,
1000                 (PGM_P)&cmd_monitor_add_action,
1001                 (PGM_P)&cmd_monitor_add_atcmd,
1002                 NULL,
1003         },
1004 };
1005
1006 /* ************* */
1007
1008 /* this structure is filled when cmd_monitor_period is parsed successfully */
1009 struct cmd_monitor_period_result {
1010         fixed_string_t monitor;
1011         fixed_string_t action;
1012         uint32_t period;
1013 };
1014
1015 /* function called when cmd_monitor_period is parsed successfully */
1016 static void cmd_monitor_period_parsed(void *parsed_result, void *data)
1017 {
1018         struct cmd_monitor_period_result *res = parsed_result;
1019
1020         (void)data;
1021         if (res->period < 100) {
1022                 printf_P(PSTR("error, minimum period is 100 ms\r\n"));
1023                 return;
1024         }
1025
1026         monitor_period_ms = res->period;
1027 }
1028
1029 const char PROGMEM str_monitor_period[] = "period";
1030
1031 const parse_token_string_t PROGMEM cmd_monitor_period_monitor_period =
1032         TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, monitor,
1033                                  str_monitor);
1034 const parse_token_string_t PROGMEM cmd_monitor_period_action =
1035         TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, action,
1036                                  str_monitor_period);
1037 const parse_token_num_t PROGMEM cmd_monitor_period_period =
1038         TOKEN_NUM_INITIALIZER(struct cmd_monitor_period_result, period, UINT32);
1039
1040
1041 const char PROGMEM help_monitor_period[] = "set register monitoring period";
1042
1043 const parse_inst_t PROGMEM cmd_monitor_period = {
1044         .f = cmd_monitor_period_parsed,  /* function to call */
1045         .data = NULL,      /* 2nd arg of func */
1046         .help_str = help_monitor_period,
1047         .tokens = {        /* token list, NULL terminated */
1048                 (PGM_P)&cmd_monitor_period_monitor_period,
1049                 (PGM_P)&cmd_monitor_period_action,
1050                 (PGM_P)&cmd_monitor_period_period,
1051                 NULL,
1052         },
1053 };
1054
1055 /* ************* */
1056
1057 /* this structure is filled when cmd_monitor_del is parsed successfully */
1058 struct cmd_monitor_del_result {
1059         fixed_string_t monitor;
1060         fixed_string_t action;
1061         struct monitor_reg *m;
1062 };
1063
1064 /* function called when cmd_monitor_del is parsed successfully */
1065 static void cmd_monitor_del_parsed(void *parsed_result, void *data)
1066 {
1067         struct cmd_monitor_del_result *res = parsed_result;
1068
1069         (void)data;
1070         monitor_current = LIST_NEXT(res->m, next);
1071         LIST_REMOVE(res->m, next);
1072         free(res->m);
1073         monitor_count --;
1074         if (monitor_count == 0) {
1075                 printf_P(PSTR("Disable monitoring, no more event\r\n"));
1076                 callout_stop(&cm, &monitor_event);
1077                 monitor_running = 0;
1078                 return;
1079         }
1080 }
1081
1082 const char PROGMEM str_monitor_del[] = "del";
1083
1084 const parse_token_string_t PROGMEM cmd_monitor_del_monitor_del =
1085         TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, monitor,
1086                                  str_monitor);
1087 const parse_token_string_t PROGMEM cmd_monitor_del_action =
1088         TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, action,
1089                                  str_monitor_del);
1090 const parse_token_monitor_t PROGMEM cmd_monitor_del_atcmd =
1091         TOKEN_MONITOR_INITIALIZER(struct cmd_monitor_del_result, m);
1092
1093
1094 const char PROGMEM help_monitor_del[] = "del a register in monitor list";
1095
1096 const parse_inst_t PROGMEM cmd_monitor_del = {
1097         .f = cmd_monitor_del_parsed,  /* function to call */
1098         .data = NULL,      /* 2nd arg of func */
1099         .help_str = help_monitor_del,
1100         .tokens = {        /* token list, NULL terminated */
1101                 (PGM_P)&cmd_monitor_del_monitor_del,
1102                 (PGM_P)&cmd_monitor_del_action,
1103                 (PGM_P)&cmd_monitor_del_atcmd,
1104                 NULL,
1105         },
1106 };
1107
1108
1109 /* ************* */
1110
1111 /* this structure is filled when cmd_ping is parsed successfully */
1112 struct cmd_ping_result {
1113         fixed_string_t ping;
1114 };
1115
1116 /* function called when cmd_ping is parsed successfully */
1117 static void cmd_ping_parsed(void *parsed_result, void *data)
1118 {
1119         (void)parsed_result;
1120         (void)data;
1121         xbeeapp_send_atcmd("VL", NULL, 0, 1, NULL, NULL);
1122 }
1123
1124 const char PROGMEM str_ping[] = "ping";
1125
1126 const parse_token_string_t PROGMEM cmd_ping_ping =
1127         TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping,
1128                                  str_ping);
1129
1130 const char PROGMEM help_ping[] = "Send a ping to the xbee device";
1131
1132 const parse_inst_t PROGMEM cmd_ping = {
1133         .f = cmd_ping_parsed,  /* function to call */
1134         .data = NULL,      /* 2nd arg of func */
1135         .help_str = help_ping,
1136         .tokens = {        /* token list, NULL terminated */
1137                 (PGM_P)&cmd_ping_ping,
1138                 NULL,
1139         },
1140 };
1141
1142 /* ************* */
1143
1144 /* this structure is filled when cmd_raw is parsed successfully */
1145 struct cmd_raw_result {
1146         fixed_string_t raw;
1147 };
1148
1149 /* function called when cmd_raw is parsed successfully */
1150 static void cmd_raw_parsed(void *parsed_result, void *data)
1151 {
1152         (void)parsed_result;
1153         (void)data;
1154         printf_P(PSTR("switched to raw mode, CTRL-D to exit\r\n"));
1155         rdline_stop(&xbeeboard.rdl); /* don't display prompt when return */
1156         xbee_raw = 1;
1157 }
1158
1159 const char PROGMEM str_raw[] = "raw";
1160
1161 const parse_token_string_t PROGMEM cmd_raw_raw =
1162         TOKEN_STRING_INITIALIZER(struct cmd_raw_result, raw,
1163                                  str_raw);
1164
1165 const char PROGMEM help_raw[] = "Switch to raw mode";
1166
1167 const parse_inst_t PROGMEM cmd_raw = {
1168         .f = cmd_raw_parsed,  /* function to call */
1169         .data = NULL,      /* 2nd arg of func */
1170         .help_str = help_raw,
1171         .tokens = {        /* token list, NULL terminated */
1172                 (PGM_P)&cmd_raw_raw,
1173                 NULL,
1174         },
1175 };
1176
1177 /* ************* */
1178
1179 /* this structure is filled when cmd_dump is parsed successfully */
1180 struct cmd_dump_result {
1181         fixed_string_t dump;
1182         fixed_string_t onoff;
1183 };
1184
1185 /* function called when cmd_dump is parsed successfully */
1186 static void cmd_dump_parsed(void *parsed_result, void *data)
1187 {
1188         struct cmd_dump_result *res = parsed_result;
1189
1190         (void)data;
1191         if (!strcmp(res->onoff, "on"))
1192                 xbee_hexdump = 1;
1193         else
1194                 xbee_hexdump = 0;
1195 }
1196
1197 const char PROGMEM str_dump[] = "dump";
1198 const char PROGMEM str_dump_onoff[] = "on#off";
1199
1200 const parse_token_string_t PROGMEM cmd_dump_dump =
1201         TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump,
1202                                  str_dump);
1203
1204 const parse_token_string_t PROGMEM cmd_dump_onoff =
1205         TOKEN_STRING_INITIALIZER(struct cmd_dump_result, onoff,
1206                                  str_dump_onoff);
1207
1208 const char PROGMEM help_dump[] = "enable/disable hexdump of received packets";
1209
1210 const parse_inst_t PROGMEM cmd_dump = {
1211         .f = cmd_dump_parsed,  /* function to call */
1212         .data = NULL,      /* 2nd arg of func */
1213         .help_str = help_dump,
1214         .tokens = {        /* token list, NULL terminated */
1215                 (PGM_P)&cmd_dump_dump,
1216                 (PGM_P)&cmd_dump_onoff,
1217                 NULL,
1218         },
1219 };
1220
1221 /* ************* */
1222
1223 /* this structure is filled when cmd_debug is parsed successfully */
1224 struct cmd_debug_result {
1225         fixed_string_t debug;
1226         fixed_string_t onoff;
1227 };
1228
1229 /* function called when cmd_debug is parsed successfully */
1230 static void cmd_debug_parsed(void *parsed_result, void *data)
1231 {
1232         struct cmd_debug_result *res = parsed_result;
1233
1234         (void)data;
1235         if (!strcmp(res->onoff, "on"))
1236                 xbee_debug = 1;
1237         else
1238                 xbee_debug = 0;
1239 }
1240
1241 const char PROGMEM str_debug[] = "debug";
1242 const char PROGMEM str_debug_onoff[] = "on#off";
1243
1244 const parse_token_string_t PROGMEM cmd_debug_debug =
1245         TOKEN_STRING_INITIALIZER(struct cmd_debug_result, debug,
1246                                  str_debug);
1247
1248 const parse_token_string_t PROGMEM cmd_debug_onoff =
1249         TOKEN_STRING_INITIALIZER(struct cmd_debug_result, onoff,
1250                                  str_debug_onoff);
1251
1252 const char PROGMEM help_debug[] = "enable/disable additionnal debug";
1253
1254 const parse_inst_t PROGMEM cmd_debug = {
1255         .f = cmd_debug_parsed,  /* function to call */
1256         .data = NULL,      /* 2nd arg of func */
1257         .help_str = help_debug,
1258         .tokens = {        /* token list, NULL terminated */
1259                 (PGM_P)&cmd_debug_debug,
1260                 (PGM_P)&cmd_debug_onoff,
1261                 NULL,
1262         },
1263 };
1264
1265 /**********************************************************/
1266
1267 /* this structure is filled when cmd_baudrate is parsed successfully */
1268 struct cmd_baudrate_result {
1269         fixed_string_t arg0;
1270         uint32_t arg1;
1271 };
1272
1273 /* function called when cmd_baudrate is parsed successfully */
1274 static void cmd_baudrate_parsed(void * parsed_result, __attribute__((unused)) void *data)
1275 {
1276         struct cmd_baudrate_result *res = parsed_result;
1277         struct uart_config c;
1278
1279         uart_getconf(XBEE_UART, &c);
1280         c.baudrate = res->arg1;
1281         uart_setconf(XBEE_UART, &c);
1282 }
1283
1284 const char PROGMEM str_baudrate_arg0[] = "baudrate";
1285 const parse_token_string_t PROGMEM cmd_baudrate_arg0 =
1286         TOKEN_STRING_INITIALIZER(struct cmd_baudrate_result, arg0,
1287                                  str_baudrate_arg0);
1288 const parse_token_num_t PROGMEM cmd_baudrate_arg1 =
1289         TOKEN_NUM_INITIALIZER(struct cmd_baudrate_result, arg1,
1290                               UINT32);
1291
1292 const char PROGMEM help_baudrate[] = "Change xbee baudrate";
1293 const parse_inst_t PROGMEM cmd_baudrate = {
1294         .f = cmd_baudrate_parsed,  /* function to call */
1295         .data = NULL,      /* 2nd arg of func */
1296         .help_str = help_baudrate,
1297         .tokens = {        /* token list, NULL terminated */
1298                 (PGM_P)&cmd_baudrate_arg0,
1299                 (PGM_P)&cmd_baudrate_arg1,
1300                 NULL,
1301         },
1302 };
1303
1304
1305 /**********************************************************/
1306
1307 /* this structure is filled when cmd_beep is parsed successfully */
1308 struct cmd_beep_result {
1309         fixed_string_t beep;
1310 };
1311
1312 /* function called when cmd_beep is parsed successfully */
1313 static void cmd_beep_parsed(void *parsed_result, void *data)
1314 {
1315         (void)parsed_result;
1316         (void)data;
1317
1318         beep(0, 3, 3);
1319         beep(1, 3, 3);
1320         beep(2, 3, 3);
1321         beep(0, 1, 1);
1322         beep(1, 1, 1);
1323         beep(2, 1, 1);
1324 }
1325
1326 const char PROGMEM str_beep[] = "beep";
1327 const parse_token_string_t PROGMEM cmd_beep_beep =
1328         TOKEN_STRING_INITIALIZER(struct cmd_beep_result, beep,
1329                                  str_beep);
1330
1331 const char PROGMEM help_beep[] = "Send a beep";
1332
1333 const parse_inst_t PROGMEM cmd_beep = {
1334         .f = cmd_beep_parsed,  /* function to call */
1335         .data = NULL,      /* 2nd arg of func */
1336         .help_str = help_beep,
1337         .tokens = {        /* token list, NULL terminated */
1338                 (PGM_P)&cmd_beep_beep,
1339                 NULL,
1340         },
1341 };
1342
1343 /**********************************************************/
1344
1345 /* this structure is filled when cmd_servo is parsed successfully */
1346 struct cmd_servo_result {
1347         fixed_string_t arg0;
1348         fixed_string_t arg1;
1349         uint16_t num;
1350         uint16_t val;
1351 };
1352
1353 /* function called when cmd_servo is parsed successfully */
1354 static void cmd_servo_parsed(void * parsed_result, void *data)
1355 {
1356         struct cmd_servo_result *res = parsed_result;
1357
1358         (void)data;
1359
1360         if (!strcmp_P(res->arg1, PSTR("set"))) {
1361                 if (res->num >= N_SERVO) {
1362                         printf_P(PSTR("bad servo num\n"));
1363                         return;
1364                 }
1365                 if (res->val >= 1024) {
1366                         printf_P(PSTR("bad servo val\n"));
1367                         return;
1368                 }
1369                 spi_servo_set(res->num, res->val);
1370         }
1371         else if (!strcmp_P(res->arg1, PSTR("bypass"))) {
1372                 spi_servo_set_bypass(!!res->val);
1373         }
1374         else if (!strcmp_P(res->arg1, PSTR("ppm"))) {
1375                 spi_servo_set_ppm(!!res->val);
1376         }
1377         else if (!strcmp_P(res->arg1, PSTR("show"))) {
1378                 spi_servo_dump();
1379         }
1380 }
1381
1382 const char PROGMEM str_servo_arg0[] = "servo";
1383 const parse_token_string_t PROGMEM cmd_servo_arg0 =
1384         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg0,
1385                                  str_servo_arg0);
1386 const char PROGMEM str_servo_arg1_set[] = "set";
1387 const parse_token_string_t PROGMEM cmd_servo_arg1_set =
1388         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1389                                  str_servo_arg1_set);
1390 const parse_token_num_t PROGMEM cmd_servo_num =
1391         TOKEN_NUM_INITIALIZER(struct cmd_servo_result, num,
1392                               UINT16);
1393 const parse_token_num_t PROGMEM cmd_servo_val =
1394         TOKEN_NUM_INITIALIZER(struct cmd_servo_result, val,
1395                               UINT16);
1396
1397 const char PROGMEM help_servo_set[] = "set servo value";
1398 const parse_inst_t PROGMEM cmd_servo_set = {
1399         .f = cmd_servo_parsed,  /* function to call */
1400         .data = NULL,      /* 2nd arg of func */
1401         .help_str = help_servo_set,
1402         .tokens = {        /* token list, NULL terminated */
1403                 (PGM_P)&cmd_servo_arg0,
1404                 (PGM_P)&cmd_servo_arg1_set,
1405                 (PGM_P)&cmd_servo_num,
1406                 (PGM_P)&cmd_servo_val,
1407                 NULL,
1408         },
1409 };
1410
1411 const char PROGMEM str_servo_arg1_show[] = "show";
1412 const parse_token_string_t PROGMEM cmd_servo_arg1_show =
1413         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1414                                  str_servo_arg1_show);
1415
1416 const char PROGMEM help_servo_show[] = "read servo and config";
1417 const parse_inst_t PROGMEM cmd_servo_show = {
1418         .f = cmd_servo_parsed,  /* function to call */
1419         .data = NULL,      /* 2nd arg of func */
1420         .help_str = help_servo_show,
1421         .tokens = {        /* token list, NULL terminated */
1422                 (PGM_P)&cmd_servo_arg0,
1423                 (PGM_P)&cmd_servo_arg1_show,
1424                 NULL,
1425         },
1426 };
1427
1428 const char PROGMEM str_servo_arg1_bypassppm[] = "bypass#ppm";
1429 const parse_token_string_t PROGMEM cmd_servo_arg1_bypassppm =
1430         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1431                                  str_servo_arg1_bypassppm);
1432
1433 const char PROGMEM help_servo_bypassppm[] = "change bypass/ppm";
1434 const parse_inst_t PROGMEM cmd_servo_bypassppm = {
1435         .f = cmd_servo_parsed,  /* function to call */
1436         .data = NULL,      /* 2nd arg of func */
1437         .help_str = help_servo_bypassppm,
1438         .tokens = {        /* token list, NULL terminated */
1439                 (PGM_P)&cmd_servo_arg0,
1440                 (PGM_P)&cmd_servo_arg1_bypassppm,
1441                 (PGM_P)&cmd_servo_val,
1442                 NULL,
1443         },
1444 };
1445
1446 /**********************************************************/
1447
1448 /* this structure is filled when cmd_test_spi is parsed successfully */
1449 struct cmd_test_spi_result {
1450         fixed_string_t arg0;
1451 };
1452
1453 static void cmd_test_spi_parsed(void * parsed_result, void *data)
1454 {
1455         uint8_t i, flags, wait_time = 0;
1456         uint16_t val = 0;
1457
1458         (void)parsed_result;
1459         (void)data;
1460
1461         spi_servo_set_bypass(0);
1462         spi_servo_set_ppm(0);
1463
1464         /* stress test: send many commands, no wait between each servo
1465          * of a series, and a variable delay between series */
1466         printf_P(PSTR("stress test\r\n"));
1467         while (!cmdline_keypressed()) {
1468
1469                 wait_time++;
1470                 if (wait_time > 20)
1471                         wait_time = 0;
1472
1473                 IRQ_LOCK(flags);
1474                 val = global_ms;
1475                 IRQ_UNLOCK(flags);
1476                 val >>= 3;
1477                 val &= 1023;
1478
1479                 for (i = 0; i < 6; i++)
1480                         spi_servo_set(i, val);
1481
1482                 wait_ms(wait_time);
1483                 printf_P(PSTR("%4.4d %4.4d %4.4d %4.4d %4.4d %4.4d\r\n"),
1484                          spi_servo_get(0), spi_servo_get(1), spi_servo_get(2),
1485                          spi_servo_get(3), spi_servo_get(4), spi_servo_get(5));
1486         }
1487
1488         printf_P(PSTR("bypass mode, with spi commands in background\r\n"));
1489         spi_servo_set_bypass(1);
1490
1491         /* test bypass mode */
1492         while (!cmdline_keypressed()) {
1493
1494                 wait_time++;
1495                 if (wait_time > 20)
1496                         wait_time = 0;
1497
1498                 IRQ_LOCK(flags);
1499                 val = global_ms;
1500                 IRQ_UNLOCK(flags);
1501                 val >>= 3;
1502                 val &= 1023;
1503
1504                 for (i = 0; i < 6; i++)
1505                         spi_servo_set(i, val);
1506
1507                 wait_ms(wait_time);
1508                 printf_P(PSTR("%4.4d %4.4d %4.4d %4.4d %4.4d %4.4d\r\n"),
1509                          spi_servo_get(0), spi_servo_get(1), spi_servo_get(2),
1510                          spi_servo_get(3), spi_servo_get(4), spi_servo_get(5));
1511         }
1512
1513         printf_P(PSTR("PPM to servo\r\n"));
1514         spi_servo_set_bypass(0);
1515         spi_servo_set_ppm(0);
1516
1517         /* test PPM to servo (bypass) mode */
1518         while (!cmdline_keypressed()) {
1519                 for (i = 0; i < 6; i++) {
1520                         val = spi_servo_get(i);
1521                         spi_servo_set(i, val);
1522                 }
1523         }
1524
1525         printf_P(PSTR("PPM to (servo + PPM)\r\n"));
1526         spi_servo_set_bypass(0);
1527         spi_servo_set_ppm(1);
1528
1529         /* test PPM to servo (bypass) mode */
1530         while (!cmdline_keypressed()) {
1531                 for (i = 0; i < 6; i++) {
1532                         val = spi_servo_get(i);
1533                         spi_servo_set(i, val);
1534                 }
1535         }
1536 }
1537
1538 const char PROGMEM str_test_spi_arg0[] = "test_spi";
1539 const parse_token_string_t PROGMEM cmd_test_spi_arg0 =
1540         TOKEN_STRING_INITIALIZER(struct cmd_test_spi_result, arg0,
1541                                  str_test_spi_arg0);
1542
1543 const char PROGMEM help_test_spi[] = "Test the spi";
1544 const parse_inst_t PROGMEM cmd_test_spi = {
1545         .f = cmd_test_spi_parsed,  /* function to call */
1546         .data = NULL,      /* 2nd arg of func */
1547         .help_str = help_test_spi,
1548         .tokens = {        /* token list, NULL terminated */
1549                 (PGM_P)&cmd_test_spi_arg0,
1550                 NULL,
1551         },
1552 };
1553
1554 /**********************************************************/
1555
1556 /* this structure is filled when cmd_test_eeprom_config is parsed successfully */
1557 struct cmd_test_eeprom_config_result {
1558         fixed_string_t arg0;
1559 };
1560
1561 static void cmd_test_eeprom_config_parsed(void *parsed_result, void *data)
1562 {
1563         (void)parsed_result;
1564         (void)data;
1565
1566         eeprom_dump_cmds();
1567         eeprom_append_cmd("salut1\n");
1568         eeprom_dump_cmds();
1569         eeprom_append_cmd("salut2\n");
1570         eeprom_append_cmd("salut3\n");
1571         eeprom_append_cmd("salut4\n");
1572         eeprom_dump_cmds();
1573         eeprom_insert_cmd_before("coin\n", 0);
1574         eeprom_insert_cmd_before("coin2\n", 2);
1575         eeprom_dump_cmds();
1576         eeprom_delete_cmd(2);
1577         eeprom_delete_cmd(0);
1578         eeprom_dump_cmds();
1579 }
1580
1581 const char PROGMEM str_test_eeprom_config_arg0[] = "test_eeprom_config";
1582 const parse_token_string_t PROGMEM cmd_test_eeprom_config_arg0 =
1583         TOKEN_STRING_INITIALIZER(struct cmd_test_eeprom_config_result, arg0,
1584                                  str_test_eeprom_config_arg0);
1585
1586 const char PROGMEM help_test_eeprom_config[] = "Test the eeprom configuration";
1587 const parse_inst_t PROGMEM cmd_test_eeprom_config = {
1588         .f = cmd_test_eeprom_config_parsed,  /* function to call */
1589         .data = NULL,      /* 2nd arg of func */
1590         .help_str = help_test_eeprom_config,
1591         .tokens = {        /* token list, NULL terminated */
1592                 (PGM_P)&cmd_test_eeprom_config_arg0,
1593                 NULL,
1594         },
1595 };
1596
1597 /* ************* */
1598
1599 struct cmd_eeprom_del_result {
1600         fixed_string_t cmd;
1601         fixed_string_t action;
1602         uint8_t n;
1603 };
1604
1605 static void cmd_eeprom_del_parsed(void *parsed_result,
1606                                 void *data)
1607 {
1608         struct cmd_eeprom_del_result *res = parsed_result;
1609
1610         (void)data;
1611         if (eeprom_delete_cmd(res->n) < 0)
1612                 printf_P(PSTR("cannot delete command\n"));
1613         eeprom_dump_cmds();
1614 }
1615
1616 const char PROGMEM str_eeprom_del_eeprom[] = "eeprom";
1617 const parse_token_string_t PROGMEM cmd_eeprom_del_cmd =
1618         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_del_result, cmd,
1619                                  str_eeprom_del_eeprom);
1620 const char PROGMEM str_eeprom_del_del[] = "del";
1621 const parse_token_string_t PROGMEM cmd_eeprom_del_action =
1622         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_del_result, action,
1623                                  str_eeprom_del_del);
1624 const parse_token_num_t PROGMEM cmd_eeprom_del_num =
1625         TOKEN_NUM_INITIALIZER(struct cmd_eeprom_del_result, n,
1626                               UINT8);
1627
1628 const char PROGMEM help_eeprom_del[] = "delete an eeprom init command";
1629 const parse_inst_t PROGMEM cmd_eeprom_del = {
1630         .f = cmd_eeprom_del_parsed,  /* function to call */
1631         .data = NULL,      /* 2nd arg of func */
1632         .help_str = help_eeprom_del,
1633         .tokens = {        /* token list, NULL terminated */
1634                 (PGM_P)&cmd_eeprom_del_cmd,
1635                 (PGM_P)&cmd_eeprom_del_action,
1636                 (PGM_P)&cmd_eeprom_del_num,
1637                 NULL,
1638         },
1639 };
1640
1641 /* ************* */
1642
1643 struct cmd_eeprom_add_result {
1644         fixed_string_t cmd;
1645         fixed_string_t action;
1646         uint8_t n;
1647 };
1648
1649 static void cmd_eeprom_add_parsed(void *parsed_result,
1650                                  void *data)
1651 {
1652         struct cmd_eeprom_add_result *res = parsed_result;
1653         struct rdline rdl;
1654         const char *buffer;
1655         int8_t ret;
1656         int16_t c;
1657
1658         rdline_init(&rdl, cmdline_write_char, NULL, NULL);
1659         rdline_newline(&rdl, "> ");
1660
1661         /* XXX bad: we should not block as we do not serve callout */
1662         while (1) {
1663                 c = cmdline_dev_recv(NULL);
1664                 if (c < 0)
1665                         continue;
1666
1667                 ret = rdline_char_in(&rdl, c);
1668                 if (ret == -2) {
1669                         printf_P(PSTR("abort\n"));
1670                         return;
1671                 }
1672                 if (ret == 1)
1673                         break;
1674         }
1675
1676         buffer = rdline_get_buffer(&rdl);
1677         if (data == NULL)
1678                 eeprom_insert_cmd_before(buffer, res->n);
1679         else
1680                 eeprom_append_cmd(buffer);
1681         eeprom_dump_cmds();
1682 }
1683
1684 const char PROGMEM str_eeprom_add_eeprom[] = "eeprom";
1685 const parse_token_string_t PROGMEM cmd_eeprom_add_cmd =
1686         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_add_result, cmd,
1687                                  str_eeprom_add_eeprom);
1688 const char PROGMEM str_eeprom_add_add[] = "add";
1689 const parse_token_string_t PROGMEM cmd_eeprom_add_action =
1690         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_add_result, action,
1691                                  str_eeprom_add_add);
1692 const parse_token_num_t PROGMEM cmd_eeprom_add_num =
1693         TOKEN_NUM_INITIALIZER(struct cmd_eeprom_add_result, n,
1694                               UINT8);
1695
1696 const char PROGMEM help_eeprom_add[] = "insert an eeprom init command";
1697 const parse_inst_t PROGMEM cmd_eeprom_add = {
1698         .f = cmd_eeprom_add_parsed,  /* function to call */
1699         .data = NULL,      /* 2nd arg of func */
1700         .help_str = help_eeprom_add,
1701         .tokens = {        /* token list, NULL terminated */
1702                 (PGM_P)&cmd_eeprom_add_cmd,
1703                 (PGM_P)&cmd_eeprom_add_action,
1704                 (PGM_P)&cmd_eeprom_add_num,
1705                 NULL,
1706         },
1707 };
1708
1709 const char PROGMEM help_eeprom_add2[] = "append an eeprom init command";
1710 const parse_inst_t PROGMEM cmd_eeprom_add2 = {
1711         .f = cmd_eeprom_add_parsed,  /* function to call */
1712         .data = (void *)1,      /* 2nd arg of func */
1713         .help_str = help_eeprom_add2,
1714         .tokens = {        /* token list, NULL terminated */
1715                 (PGM_P)&cmd_eeprom_add_cmd,
1716                 (PGM_P)&cmd_eeprom_add_action,
1717                 NULL,
1718         },
1719 };
1720
1721 /* ************* */
1722
1723 struct cmd_eeprom_list_result {
1724         fixed_string_t cmd;
1725         fixed_string_t action;
1726 };
1727
1728 static void cmd_eeprom_list_parsed(void *parsed_result,
1729                                 void *data)
1730 {
1731         (void)parsed_result;
1732         (void)data;
1733         eeprom_dump_cmds();
1734 }
1735
1736 const char PROGMEM str_eeprom_list_eeprom[] = "eeprom";
1737 const parse_token_string_t PROGMEM cmd_eeprom_list_cmd =
1738         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_list_result, cmd,
1739                                  str_eeprom_list_eeprom);
1740 const char PROGMEM str_eeprom_list_list[] = "list";
1741 const parse_token_string_t PROGMEM cmd_eeprom_list_action =
1742         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_list_result, action,
1743                                  str_eeprom_list_list);
1744
1745 const char PROGMEM help_eeprom_list[] = "list all eeprom init commands";
1746 const parse_inst_t PROGMEM cmd_eeprom_list = {
1747         .f = cmd_eeprom_list_parsed,  /* function to call */
1748         .data = NULL,      /* 2nd arg of func */
1749         .help_str = help_eeprom_list,
1750         .tokens = {        /* token list, NULL terminated */
1751                 (PGM_P)&cmd_eeprom_list_cmd,
1752                 (PGM_P)&cmd_eeprom_list_action,
1753                 NULL,
1754         },
1755 };
1756
1757
1758 /* ************* */
1759
1760 /* in progmem */
1761 const parse_ctx_t PROGMEM main_ctx[] = {
1762
1763         /* commands_gen.c */
1764         &cmd_reset,
1765         &cmd_bootloader,
1766         &cmd_log,
1767         &cmd_log_show,
1768         &cmd_log_type,
1769         &cmd_stack_space,
1770         &cmd_scheduler,
1771         &cmd_help,
1772         &cmd_neigh_del,
1773         &cmd_neigh_add,
1774         &cmd_neigh_list,
1775         &cmd_read,
1776         &cmd_write_none,
1777         &cmd_write_u8,
1778         &cmd_write_u16,
1779         &cmd_write_u32,
1780         &cmd_sendmsg,
1781         &cmd_sendmsg_name,
1782         &cmd_range,
1783         &cmd_range_period,
1784         &cmd_range_count,
1785         &cmd_range_powermask,
1786         &cmd_range_dstaddr,
1787         &cmd_monitor,
1788         &cmd_monitor_period,
1789         &cmd_monitor_add,
1790         &cmd_monitor_del,
1791         &cmd_ping,
1792         &cmd_raw,
1793         &cmd_dump,
1794         &cmd_debug,
1795         &cmd_baudrate,
1796         &cmd_beep,
1797         &cmd_servo_set,
1798         &cmd_servo_bypassppm,
1799         &cmd_servo_show,
1800         &cmd_test_spi,
1801         &cmd_test_eeprom_config,
1802         &cmd_eeprom_del,
1803         &cmd_eeprom_add,
1804         &cmd_eeprom_add2,
1805         &cmd_eeprom_list,
1806         NULL,
1807 };