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