weak current limit on spickles
[aversive.git] / projects / microb2010 / mainboard / commands_gen.c
1 /*
2  *  Copyright Droids Corporation (2008)
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_gen.c,v 1.8 2009-11-08 17:24:33 zer0 Exp $
19  *
20  *  Olivier MATZ <zer0@droids-corp.org> 
21  */
22
23 #include <stdio.h>
24 #include <string.h>
25
26 #include <aversive/pgmspace.h>
27 #include <aversive/wait.h>
28 #include <aversive/error.h>
29
30 #include <hostsim.h>
31 #include <ax12.h>
32 #include <uart.h>
33 #include <pwm_ng.h>
34 #include <clock_time.h>
35 #include <encoders_spi.h>
36 #include <adc.h>
37
38 #include <scheduler.h>
39 #include <scheduler_stats.h>
40 #include <pid.h>
41 #include <quadramp.h>
42 #include <control_system_manager.h>
43 #include <trajectory_manager.h>
44 #include <vect_base.h>
45 #include <lines.h>
46 #include <polygon.h>
47 #include <obstacle_avoidance.h>
48 #include <blocking_detection_manager.h>
49 #include <robot_system.h>
50 #include <position_manager.h>
51
52 #include <rdline.h>
53 #include <parse.h>
54 #include <parse_string.h>
55 #include <parse_num.h>
56
57 #include <diagnostic.h>
58
59 #include "main.h"
60 #include "cmdline.h"
61 #include "sensor.h"
62
63 /**********************************************************/
64 /* Reset */
65
66 /* this structure is filled when cmd_reset is parsed successfully */
67 struct cmd_reset_result {
68         fixed_string_t arg0;
69 };
70
71 /* function called when cmd_reset is parsed successfully */
72 static void cmd_reset_parsed(void * parsed_result, void * data)
73 {
74 #ifdef HOST_VERSION
75         hostsim_exit();
76 #endif
77         reset();
78 }
79
80 prog_char str_reset_arg0[] = "reset";
81 parse_pgm_token_string_t cmd_reset_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_reset_result, arg0, str_reset_arg0);
82
83 prog_char help_reset[] = "Reset the board";
84 parse_pgm_inst_t cmd_reset = {
85         .f = cmd_reset_parsed,  /* function to call */
86         .data = NULL,      /* 2nd arg of func */
87         .help_str = help_reset,
88         .tokens = {        /* token list, NULL terminated */
89                 (prog_void *)&cmd_reset_arg0, 
90                 NULL,
91         },
92 };
93
94 /**********************************************************/
95 /* Bootloader */
96
97 /* this structure is filled when cmd_bootloader is parsed successfully */
98 struct cmd_bootloader_result {
99         fixed_string_t arg0;
100 };
101
102 /* function called when cmd_bootloader is parsed successfully */
103 static void cmd_bootloader_parsed(void *parsed_result, void *data)
104 {
105 #ifndef HOST_VERSION
106         bootloader();
107 #else
108         printf("not implemented\n");
109 #endif
110 }
111
112 prog_char str_bootloader_arg0[] = "bootloader";
113 parse_pgm_token_string_t cmd_bootloader_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_bootloader_result, arg0, str_bootloader_arg0);
114
115 prog_char help_bootloader[] = "Launch the bootloader";
116 parse_pgm_inst_t cmd_bootloader = {
117         .f = cmd_bootloader_parsed,  /* function to call */
118         .data = NULL,      /* 2nd arg of func */
119         .help_str = help_bootloader,
120         .tokens = {        /* token list, NULL terminated */
121                 (prog_void *)&cmd_bootloader_arg0, 
122                 NULL,
123         },
124 };
125
126 /**********************************************************/
127 /* Encoders tests */
128
129 /* this structure is filled when cmd_encoders is parsed successfully */
130 struct cmd_encoders_result {
131         fixed_string_t arg0;
132         fixed_string_t arg1;
133 };
134
135 /* function called when cmd_encoders is parsed successfully */
136 static void cmd_encoders_parsed(void *parsed_result, void *data)
137 {
138 #ifdef HOST_VERSION
139         printf("not implemented\n");
140 #else
141         struct cmd_encoders_result *res = parsed_result;
142
143         if (!strcmp_P(res->arg1, PSTR("reset"))) {
144                 encoders_spi_set_value((void *)0, 0);
145                 encoders_spi_set_value((void *)1, 0);
146                 encoders_spi_set_value((void *)2, 0);
147                 encoders_spi_set_value((void *)3, 0);
148                 return;
149         }
150
151         /* show */
152         while(!cmdline_keypressed()) {
153                 printf_P(PSTR("% .8ld % .8ld % .8ld % .8ld\r\n"), 
154                          encoders_spi_get_value((void *)0),
155                          encoders_spi_get_value((void *)1),
156                          encoders_spi_get_value((void *)2),
157                          encoders_spi_get_value((void *)3));
158                 wait_ms(100);
159         }
160 #endif
161 }
162
163 prog_char str_encoders_arg0[] = "encoders";
164 parse_pgm_token_string_t cmd_encoders_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_encoders_result, arg0, str_encoders_arg0);
165 prog_char str_encoders_arg1[] = "show#reset";
166 parse_pgm_token_string_t cmd_encoders_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_encoders_result, arg1, str_encoders_arg1);
167
168 prog_char help_encoders[] = "Show encoders values";
169 parse_pgm_inst_t cmd_encoders = {
170         .f = cmd_encoders_parsed,  /* function to call */
171         .data = NULL,      /* 2nd arg of func */
172         .help_str = help_encoders,
173         .tokens = {        /* token list, NULL terminated */
174                 (prog_void *)&cmd_encoders_arg0, 
175                 (prog_void *)&cmd_encoders_arg1, 
176                 NULL,
177         },
178 };
179
180 /**********************************************************/
181 /* Scheduler show */
182
183 /* this structure is filled when cmd_scheduler is parsed successfully */
184 struct cmd_scheduler_result {
185         fixed_string_t arg0;
186         fixed_string_t arg1;
187 };
188
189 /* function called when cmd_scheduler is parsed successfully */
190 static void cmd_scheduler_parsed(void *parsed_result, void *data)
191 {
192         scheduler_dump_events();
193         scheduler_stats_dump();
194 }
195
196 prog_char str_scheduler_arg0[] = "scheduler";
197 parse_pgm_token_string_t cmd_scheduler_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_scheduler_result, arg0, str_scheduler_arg0);
198 prog_char str_scheduler_arg1[] = "show";
199 parse_pgm_token_string_t cmd_scheduler_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_scheduler_result, arg1, str_scheduler_arg1);
200
201 prog_char help_scheduler[] = "Show scheduler events";
202 parse_pgm_inst_t cmd_scheduler = {
203         .f = cmd_scheduler_parsed,  /* function to call */
204         .data = NULL,      /* 2nd arg of func */
205         .help_str = help_scheduler,
206         .tokens = {        /* token list, NULL terminated */
207                 (prog_void *)&cmd_scheduler_arg0, 
208                 (prog_void *)&cmd_scheduler_arg1, 
209                 NULL,
210         },
211 };
212
213 /**********************************************************/
214 /* Pwms tests */
215
216 /* this structure is filled when cmd_pwm is parsed successfully */
217 struct cmd_pwm_result {
218         fixed_string_t arg0;
219         fixed_string_t arg1;
220         int16_t arg2;
221 };
222
223 /* function called when cmd_pwm is parsed successfully */
224 static void cmd_pwm_parsed(void * parsed_result, void * data)
225 {
226 #ifdef HOST_VERSION
227         printf("not implemented\n");
228 #else
229         void * pwm_ptr = NULL;
230         struct cmd_pwm_result * res = parsed_result;
231         
232         if (!strcmp_P(res->arg1, PSTR("1(4A)")))
233                 pwm_ptr = &gen.pwm1_4A;
234         else if (!strcmp_P(res->arg1, PSTR("2(4B)")))
235                 pwm_ptr = &gen.pwm2_4B;
236         else if (!strcmp_P(res->arg1, PSTR("3(1A)")))
237                 pwm_ptr = &gen.pwm3_1A;
238         else if (!strcmp_P(res->arg1, PSTR("4(1B)")))
239                 pwm_ptr = &gen.pwm4_1B;
240
241         else if (!strcmp_P(res->arg1, PSTR("s1(3C)")))
242                 pwm_ptr = &gen.servo1;
243         else if (!strcmp_P(res->arg1, PSTR("s2(5A)")))
244                 pwm_ptr = &gen.servo2;
245         else if (!strcmp_P(res->arg1, PSTR("s3(5B)")))
246                 pwm_ptr = &gen.servo3;
247         else if (!strcmp_P(res->arg1, PSTR("s3(5C)")))
248                 pwm_ptr = &gen.servo4;
249         
250         if (pwm_ptr)
251                 pwm_ng_set(pwm_ptr, res->arg2);
252
253         printf_P(PSTR("done\r\n"));
254 #endif
255 }
256
257 prog_char str_pwm_arg0[] = "pwm";
258 parse_pgm_token_string_t cmd_pwm_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_pwm_result, arg0, str_pwm_arg0);
259 prog_char str_pwm_arg1[] = "1(4A)#2(4B)#3(1A)#4(1B)#s1(3C)#s2(5A)#s3(5B)#s4(5C)";
260 parse_pgm_token_string_t cmd_pwm_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_pwm_result, arg1, str_pwm_arg1);
261 parse_pgm_token_num_t cmd_pwm_arg2 = TOKEN_NUM_INITIALIZER(struct cmd_pwm_result, arg2, INT16);
262
263 prog_char help_pwm[] = "Set pwm values [-4096 ; 4095]";
264 parse_pgm_inst_t cmd_pwm = {
265         .f = cmd_pwm_parsed,  /* function to call */
266         .data = NULL,      /* 2nd arg of func */
267         .help_str = help_pwm,
268         .tokens = {        /* token list, NULL terminated */
269                 (prog_void *)&cmd_pwm_arg0, 
270                 (prog_void *)&cmd_pwm_arg1, 
271                 (prog_void *)&cmd_pwm_arg2, 
272                 NULL,
273         },
274 };
275
276 /**********************************************************/
277 /* Adcs tests */
278
279 /* this structure is filled when cmd_adc is parsed successfully */
280 struct cmd_adc_result {
281         fixed_string_t arg0;
282         fixed_string_t arg1;
283 };
284
285 /* function called when cmd_adc is parsed successfully */
286 static void cmd_adc_parsed(void *parsed_result, void *data)
287 {
288 #ifdef HOST_VERSION
289         printf("not implemented\n");
290 #else
291         struct cmd_adc_result *res = parsed_result;
292         uint8_t i, loop = 0;
293
294         if (!strcmp_P(res->arg1, PSTR("loop_show")))
295                 loop = 1;
296         
297         do {
298                 printf_P(PSTR("ADC values: "));
299                 for (i=0; i<ADC_MAX; i++) {
300                         printf_P(PSTR("%.4d "), sensor_get_adc(i));
301                 }
302                 printf_P(PSTR("\r\n"));
303                 wait_ms(100);
304         } while (loop && !cmdline_keypressed());
305 #endif
306 }
307
308 prog_char str_adc_arg0[] = "adc";
309 parse_pgm_token_string_t cmd_adc_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_adc_result, arg0, str_adc_arg0);
310 prog_char str_adc_arg1[] = "show#loop_show";
311 parse_pgm_token_string_t cmd_adc_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_adc_result, arg1, str_adc_arg1);
312
313 prog_char help_adc[] = "Show adc values";
314 parse_pgm_inst_t cmd_adc = {
315         .f = cmd_adc_parsed,  /* function to call */
316         .data = NULL,      /* 2nd arg of func */
317         .help_str = help_adc,
318         .tokens = {        /* token list, NULL terminated */
319                 (prog_void *)&cmd_adc_arg0, 
320                 (prog_void *)&cmd_adc_arg1, 
321                 NULL,
322         },
323 };
324
325
326 /**********************************************************/
327 /* Sensors tests */
328
329 /* this structure is filled when cmd_sensor is parsed successfully */
330 struct cmd_sensor_result {
331         fixed_string_t arg0;
332         fixed_string_t arg1;
333 };
334
335 /* function called when cmd_sensor is parsed successfully */
336 static void cmd_sensor_parsed(void *parsed_result, void *data)
337 {
338 #ifdef HOST_VERSION
339         printf("not implemented\n");
340 #else
341         struct cmd_sensor_result *res = parsed_result;
342         uint8_t i, loop = 0;
343
344         if (!strcmp_P(res->arg1, PSTR("loop_show")))
345                 loop = 1;
346         
347         do {
348                 printf_P(PSTR("SENSOR values: "));
349                 for (i=0; i<SENSOR_MAX; i++) {
350                         printf_P(PSTR("%d "), !!sensor_get(i));
351                 }
352                 printf_P(PSTR("\r\n"));
353                 wait_ms(100);
354         } while (loop && !cmdline_keypressed());
355 #endif
356 }
357
358 prog_char str_sensor_arg0[] = "sensor";
359 parse_pgm_token_string_t cmd_sensor_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_sensor_result, arg0, str_sensor_arg0);
360 prog_char str_sensor_arg1[] = "show#loop_show";
361 parse_pgm_token_string_t cmd_sensor_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_sensor_result, arg1, str_sensor_arg1);
362
363 prog_char help_sensor[] = "Show sensor values";
364 parse_pgm_inst_t cmd_sensor = {
365         .f = cmd_sensor_parsed,  /* function to call */
366         .data = NULL,      /* 2nd arg of func */
367         .help_str = help_sensor,
368         .tokens = {        /* token list, NULL terminated */
369                 (prog_void *)&cmd_sensor_arg0, 
370                 (prog_void *)&cmd_sensor_arg1, 
371                 NULL,
372         },
373 };
374
375
376 /**********************************************************/
377 /* Log */
378
379 /* this structure is filled when cmd_log is parsed successfully */
380 struct cmd_log_result {
381         fixed_string_t arg0;
382         fixed_string_t arg1;
383         uint8_t arg2;
384         fixed_string_t arg3;
385 };
386
387 /* keep it sync with string choice */
388 static const prog_char uart_log[] = "uart";
389 static const prog_char rs_log[] = "rs";
390 static const prog_char traj_log[] = "traj";
391 static const prog_char i2c_log[] = "i2c";
392 static const prog_char oa_log[] = "oa";
393 static const prog_char strat_log[] = "strat";
394 static const prog_char i2cproto_log[] = "i2cproto";
395 static const prog_char sensor_log[] = "sensor";
396 static const prog_char block_log[] = "bd";
397 static const prog_char cs_log[] = "cs";
398
399 struct log_name_and_num {
400         const prog_char * name;
401         uint8_t num;
402 };
403
404 static const struct log_name_and_num log_name_and_num[] = {
405         { uart_log, E_UART },
406         { rs_log, E_ROBOT_SYSTEM },
407         { traj_log, E_TRAJECTORY },
408         { i2c_log, E_I2C },
409         { oa_log, E_OA },
410         { strat_log, E_USER_STRAT },
411         { i2cproto_log, E_USER_I2C_PROTO },
412         { sensor_log, E_USER_SENSOR },
413         { block_log, E_BLOCKING_DETECTION_MANAGER },
414         { cs_log, E_USER_CS },
415 };
416
417 static uint8_t
418 log_name2num(const char * s)
419 {
420         uint8_t i;
421         
422         for (i=0; i<sizeof(log_name_and_num)/sizeof(struct log_name_and_num); i++) {
423                 if (!strcmp_P(s, log_name_and_num[i].name)) {
424                         return log_name_and_num[i].num;
425                 }
426         }
427         return 0;
428 }
429
430 const prog_char *
431 log_num2name(uint8_t num)
432 {
433         uint8_t i;
434         
435         for (i=0; i<sizeof(log_name_and_num)/sizeof(struct log_name_and_num); i++) {
436                 if (num ==  log_name_and_num[i].num) {
437                         return log_name_and_num[i].name;
438                 }
439         }
440         return NULL;
441 }
442
443 /* function called when cmd_log is parsed successfully */
444 static void cmd_log_do_show(void)
445 {
446         uint8_t i, empty=1;
447         const prog_char * name;
448
449         printf_P(PSTR("log level is %d\r\n"), gen.log_level);
450         for (i=0; i<NB_LOGS; i++) {
451                 name = log_num2name(gen.logs[i]);
452                 if (name) {
453 #ifdef HOST_VERSION
454                         printf_P(PSTR("log type %s is on\r\n"), name);
455 #else
456                         printf_P(PSTR("log type %S is on\r\n"), name);
457 #endif
458                         empty = 0;
459                 }
460         }
461         if (empty)
462                 printf_P(PSTR("no log configured\r\n"));
463 }
464
465 /* function called when cmd_log is parsed successfully */
466 static void cmd_log_parsed(void * parsed_result, void * data)
467 {
468         struct cmd_log_result *res = (struct cmd_log_result *) parsed_result;
469
470         if (!strcmp_P(res->arg1, PSTR("level"))) {
471                 gen.log_level = res->arg2;
472         }
473
474         /* else it is a show */
475         cmd_log_do_show();
476 }
477
478 prog_char str_log_arg0[] = "log";
479 parse_pgm_token_string_t cmd_log_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_log_result, arg0, str_log_arg0);
480 prog_char str_log_arg1[] = "level";
481 parse_pgm_token_string_t cmd_log_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_log_result, arg1, str_log_arg1);
482 parse_pgm_token_num_t cmd_log_arg2 = TOKEN_NUM_INITIALIZER(struct cmd_log_result, arg2, INT8);
483
484 prog_char help_log[] = "Set log options: level (0 -> 5)";
485 parse_pgm_inst_t cmd_log = {
486         .f = cmd_log_parsed,  /* function to call */
487         .data = NULL,      /* 2nd arg of func */
488         .help_str = help_log,
489         .tokens = {        /* token list, NULL terminated */
490                 (prog_void *)&cmd_log_arg0, 
491                 (prog_void *)&cmd_log_arg1, 
492                 (prog_void *)&cmd_log_arg2, 
493                 NULL,
494         },
495 };
496
497 prog_char str_log_arg1_show[] = "show";
498 parse_pgm_token_string_t cmd_log_arg1_show = TOKEN_STRING_INITIALIZER(struct cmd_log_result, arg1, str_log_arg1_show);
499
500 prog_char help_log_show[] = "Show configured logs";
501 parse_pgm_inst_t cmd_log_show = {
502         .f = cmd_log_parsed,  /* function to call */
503         .data = NULL,      /* 2nd arg of func */
504         .help_str = help_log_show,
505         .tokens = {        /* token list, NULL terminated */
506                 (prog_void *)&cmd_log_arg0, 
507                 (prog_void *)&cmd_log_arg1_show, 
508                 NULL,
509         },
510 };
511
512 /* this structure is filled when cmd_log is parsed successfully */
513 struct cmd_log_type_result {
514         fixed_string_t arg0;
515         fixed_string_t arg1;
516         fixed_string_t arg2;
517         fixed_string_t arg3;
518 };
519
520 /* function called when cmd_log is parsed successfully */
521 static void cmd_log_type_parsed(void * parsed_result, void * data)
522 {
523         struct cmd_log_type_result *res = (struct cmd_log_type_result *) parsed_result;
524         uint8_t lognum;
525         uint8_t i;
526         
527         lognum = log_name2num(res->arg2);
528         if (lognum == 0) {
529                 printf_P(PSTR("Cannot find log num\r\n"));
530                 return;
531         }
532
533         if (!strcmp_P(res->arg3, PSTR("on"))) {
534                 for (i=0; i<NB_LOGS; i++) {
535                         if (gen.logs[i] == lognum) {
536                                 printf_P(PSTR("Already on\r\n"));
537                                 return;
538                         }
539                 }
540                 for (i=0; i<NB_LOGS; i++) {
541                         if (gen.logs[i] == 0) {
542                                 gen.logs[i] = lognum;
543                                 break;
544                         }
545                 }
546                 if (i==NB_LOGS) {
547                         printf_P(PSTR("no more room\r\n"));
548                 }
549         }
550         else if (!strcmp_P(res->arg3, PSTR("off"))) {
551                 for (i=0; i<NB_LOGS; i++) {
552                         if (gen.logs[i] == lognum) {
553                                 gen.logs[i] = 0;
554                                 break;
555                         }
556                 }
557                 if (i==NB_LOGS) {
558                         printf_P(PSTR("already off\r\n"));
559                 }
560         }
561         cmd_log_do_show();
562 }
563
564 prog_char str_log_arg1_type[] = "type";
565 parse_pgm_token_string_t cmd_log_arg1_type = TOKEN_STRING_INITIALIZER(struct cmd_log_type_result, arg1, str_log_arg1_type);
566 /* keep it sync with log_name_and_num above */
567 prog_char str_log_arg2_type[] = "uart#rs#servo#traj#i2c#oa#strat#i2cproto#ext#sensor#bd#cs";
568 parse_pgm_token_string_t cmd_log_arg2_type = TOKEN_STRING_INITIALIZER(struct cmd_log_type_result, arg2, str_log_arg2_type);
569 prog_char str_log_arg3[] = "on#off";
570 parse_pgm_token_string_t cmd_log_arg3 = TOKEN_STRING_INITIALIZER(struct cmd_log_type_result, arg3, str_log_arg3);
571
572 prog_char help_log_type[] = "Set log type";
573 parse_pgm_inst_t cmd_log_type = {
574         .f = cmd_log_type_parsed,  /* function to call */
575         .data = NULL,      /* 2nd arg of func */
576         .help_str = help_log_type,
577         .tokens = {        /* token list, NULL terminated */
578                 (prog_void *)&cmd_log_arg0,
579                 (prog_void *)&cmd_log_arg1_type,
580                 (prog_void *)&cmd_log_arg2_type,
581                 (prog_void *)&cmd_log_arg3,
582                 NULL,
583         },
584 };
585
586
587 /**********************************************************/
588 /* Stack_Space */
589
590 /* this structure is filled when cmd_stack_space is parsed successfully */
591 struct cmd_stack_space_result {
592         fixed_string_t arg0;
593 };
594
595 /* function called when cmd_stack_space is parsed successfully */
596 static void cmd_stack_space_parsed(void *parsed_result, void *data)
597 {
598 #ifdef HOST_VERSION
599         printf("not implemented\n");
600 #else
601         printf("res stack: %d\r\n", min_stack_space_available());
602 #endif
603 }
604
605 prog_char str_stack_space_arg0[] = "stack_space";
606 parse_pgm_token_string_t cmd_stack_space_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_stack_space_result, arg0, str_stack_space_arg0);
607
608 prog_char help_stack_space[] = "Display remaining stack space";
609 parse_pgm_inst_t cmd_stack_space = {
610         .f = cmd_stack_space_parsed,  /* function to call */
611         .data = NULL,      /* 2nd arg of func */
612         .help_str = help_stack_space,
613         .tokens = {        /* token list, NULL terminated */
614                 (prog_void *)&cmd_stack_space_arg0, 
615                 NULL,
616         },
617 };