2 * Copyright Droids Corporation (2008)
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.
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.
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
18 * Revision : $Id: commands.c,v 1.1 2009-02-20 21:10:01 zer0 Exp $
20 * Olivier MATZ <zer0@droids-corp.org>
27 #include <aversive/pgmspace.h>
28 #include <aversive/wait.h>
33 #include <parse_num.h>
34 #include <parse_string.h>
41 #include <control_system_manager.h>
47 uint8_t addr_from_string(const char *s)
50 if (!strcmp_P(s, PSTR("cw_angle_limit")))
51 return AA_CW_ANGLE_LIMIT_L;
52 if (!strcmp_P(s, PSTR("ccw_angle_limit")))
53 return AA_CCW_ANGLE_LIMIT_L;
54 if (!strcmp_P(s, PSTR("max_torque")))
55 return AA_MAX_TORQUE_L;
56 if (!strcmp_P(s, PSTR("down_calibration")))
57 return AA_DOWN_CALIBRATION_L;
58 if (!strcmp_P(s, PSTR("up_calibration")))
59 return AA_UP_CALIBRATION_L;
60 if (!strcmp_P(s, PSTR("torque_limit")))
61 return AA_TORQUE_LIMIT_L;
62 if (!strcmp_P(s, PSTR("position")))
63 return AA_PRESENT_POSITION_L;
64 if (!strcmp_P(s, PSTR("speed")))
65 return AA_PRESENT_SPEED_L;
66 if (!strcmp_P(s, PSTR("load")))
67 return AA_PRESENT_LOAD_L;
68 if (!strcmp_P(s, PSTR("moving_speed")))
69 return AA_MOVING_SPEED_L;
70 if (!strcmp_P(s, PSTR("model")))
71 return AA_MODEL_NUMBER_L;
72 if (!strcmp_P(s, PSTR("goal_pos")))
73 return AA_GOAL_POSITION_L;
74 if (!strcmp_P(s, PSTR("punch")))
78 if (!strcmp_P(s, PSTR("firmware")))
80 if (!strcmp_P(s, PSTR("id")))
82 if (!strcmp_P(s, PSTR("baudrate")))
84 if (!strcmp_P(s, PSTR("delay")))
86 if (!strcmp_P(s, PSTR("high_lim_temp")))
87 return AA_HIGHEST_LIMIT_TEMP;
88 if (!strcmp_P(s, PSTR("low_lim_volt")))
89 return AA_LOWEST_LIMIT_VOLTAGE;
90 if (!strcmp_P(s, PSTR("high_lim_volt")))
91 return AA_HIGHEST_LIMIT_VOLTAGE;
92 if (!strcmp_P(s, PSTR("status_return")))
93 return AA_STATUS_RETURN_LEVEL;
94 if (!strcmp_P(s, PSTR("alarm_led")))
96 if (!strcmp_P(s, PSTR("alarm_shutdown")))
97 return AA_ALARM_SHUTDOWN;
98 if (!strcmp_P(s, PSTR("torque_enable")))
99 return AA_TORQUE_ENABLE;
100 if (!strcmp_P(s, PSTR("led")))
102 if (!strcmp_P(s, PSTR("cw_comp_margin")))
103 return AA_CW_COMPLIANCE_MARGIN;
104 if (!strcmp_P(s, PSTR("ccw_comp_margin")))
105 return AA_CCW_COMPLIANCE_MARGIN;
106 if (!strcmp_P(s, PSTR("cw_comp_slope")))
107 return AA_CW_COMPLIANCE_SLOPE;
108 if (!strcmp_P(s, PSTR("ccw_comp_slope")))
109 return AA_CCW_COMPLIANCE_SLOPE;
110 if (!strcmp_P(s, PSTR("voltage")))
111 return AA_PRESENT_VOLTAGE;
112 if (!strcmp_P(s, PSTR("temp")))
113 return AA_PRESENT_TEMP;
114 if (!strcmp_P(s, PSTR("reginst")))
115 return AA_PRESENT_REGINST;
116 if (!strcmp_P(s, PSTR("moving")))
118 if (!strcmp_P(s, PSTR("lock")))
126 /**********************************************************/
129 /* this structure is filled when cmd_reset is parsed successfully */
130 struct cmd_reset_result {
134 /* function called when cmd_reset is parsed successfully */
135 static void cmd_reset_parsed(void * parsed_result, void * data)
140 prog_char str_reset_arg0[] = "reset";
141 parse_pgm_token_string_t cmd_reset_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_reset_result, arg0, str_reset_arg0);
143 prog_char help_reset[] = "Reset the board";
144 parse_pgm_inst_t cmd_reset = {
145 .f = cmd_reset_parsed, /* function to call */
146 .data = NULL, /* 2nd arg of func */
147 .help_str = help_reset,
148 .tokens = { /* token list, NULL terminated */
149 (prog_void *)&cmd_reset_arg0,
154 /**********************************************************/
157 /* this structure is filled when cmd_spi_test is parsed successfully */
158 struct cmd_spi_test_result {
162 /* function called when cmd_spi_test is parsed successfully */
163 static void cmd_spi_test_parsed(void * parsed_result, void * data)
168 for (i=0; i<3; i++) {
170 ret = spi_send_and_receive_byte(i);
171 spi_slave_deselect(0);
172 printf_P(PSTR("Sent %d, received %d\r\n"), i, ret);
175 printf_P(PSTR("disabled\r\n"));
179 prog_char str_spi_test_arg0[] = "spi_test";
180 parse_pgm_token_string_t cmd_spi_test_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_spi_test_result, arg0, str_spi_test_arg0);
182 prog_char help_spi_test[] = "Test the SPI";
183 parse_pgm_inst_t cmd_spi_test = {
184 .f = cmd_spi_test_parsed, /* function to call */
185 .data = NULL, /* 2nd arg of func */
186 .help_str = help_spi_test,
187 .tokens = { /* token list, NULL terminated */
188 (prog_void *)&cmd_spi_test_arg0,
193 /**********************************************************/
196 /* this structure is filled when cmd_bootloader is parsed successfully */
197 struct cmd_bootloader_result {
201 /* function called when cmd_bootloader is parsed successfully */
202 static void cmd_bootloader_parsed(void *parsed_result, void *data)
204 #define BOOTLOADER_ADDR 0x3f000
205 if (pgm_read_byte_far(BOOTLOADER_ADDR) == 0xff) {
206 printf_P(PSTR("Bootloader is not present\r\n"));
210 /* ... very specific :( */
228 __asm__ __volatile__ ("ldi r31,0xf8\n");
229 __asm__ __volatile__ ("ldi r30,0x00\n");
230 __asm__ __volatile__ ("eijmp\n");
233 prog_char str_bootloader_arg0[] = "bootloader";
234 parse_pgm_token_string_t cmd_bootloader_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_bootloader_result, arg0, str_bootloader_arg0);
236 prog_char help_bootloader[] = "Launch the bootloader";
237 parse_pgm_inst_t cmd_bootloader = {
238 .f = cmd_bootloader_parsed, /* function to call */
239 .data = NULL, /* 2nd arg of func */
240 .help_str = help_bootloader,
241 .tokens = { /* token list, NULL terminated */
242 (prog_void *)&cmd_bootloader_arg0,
247 /**********************************************************/
250 /* this structure is filled when cmd_ax12_stress is parsed successfully */
251 struct cmd_ax12_stress_result {
255 /* function called when cmd_ax12_stress is parsed successfully */
256 static void cmd_ax12_stress_parsed(void * parsed_result, void * data)
260 microseconds t = time_get_us2();
262 for (i=0; i<1000; i++) {
263 if (AX12_read_byte(&ax12, 3, AA_ID, &val) != 0)
267 printf_P(PSTR("%d errors / 1000\r\n"), nb_errs);
268 t = (time_get_us2() - t) / 1000;
269 printf_P(PSTR("Test done in %d ms\r\n"), (int)t);
272 prog_char str_ax12_stress_arg0[] = "ax12_stress";
273 parse_pgm_token_string_t cmd_ax12_stress_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_ax12_stress_result, arg0, str_ax12_stress_arg0);
275 prog_char help_ax12_stress[] = "Ax12_Stress the board";
276 parse_pgm_inst_t cmd_ax12_stress = {
277 .f = cmd_ax12_stress_parsed, /* function to call */
278 .data = NULL, /* 2nd arg of func */
279 .help_str = help_ax12_stress,
280 .tokens = { /* token list, NULL terminated */
281 (prog_void *)&cmd_ax12_stress_arg0,
286 /**********************************************************/
289 /* this structure is filled when cmd_test is parsed successfully */
290 struct cmd_test_result {
296 void arm_goto(int32_t shoulder, uint16_t elbow, uint16_t wrist)
300 printf("%ld %d\r\n", shoulder, elbow);
301 cs_set_consign(&arm.cs_mot, shoulder);
302 err = AX12_write_int(&ax12, ELBOW_AX12, AA_GOAL_POSITION_L, elbow);
304 AX12_write_int(&ax12, WRIST_AX12, AA_GOAL_POSITION_L, wrist);
306 printf_P(PSTR("AX12 error %x !\r\n"), err);
309 #define arm_take_high_v1() arm_goto(-18700, 204, 455)
310 #define arm_take_low_v1() arm_goto(-11000, 273, 480)
311 #define arm_take_high_v2() arm_goto(-18700, 204, 154)
312 #define arm_take_low_v2() arm_goto(-11000, 273, 139)
313 #define arm_intermediate() arm_goto(-35700, 297, 385)
314 #define arm_drop_v2() arm_goto(-16810, 667, 564)
315 #define arm_drop_v1() arm_goto(-16810, 667, 904)
317 /* function called when cmd_test is parsed successfully */
318 static void cmd_test_parsed(void * parsed_result, void * data)
323 /* Set some AX12 parameters */
324 /* err = AX12_write_int(&ax12,0xFE,AA_TORQUE_ENABLE,0x1); */
326 /* AX12_write_int(&ax12,0xFE,AA_PUNCH_L,0x20); */
328 /* AX12_write_int(&ax12,0xFE,AA_TORQUE_LIMIT_L,0x3FF); */
330 /* AX12_write_int(&ax12,0xFE,AA_MOVING_SPEED_L,0x3FF); */
332 /* AX12_write_byte(&ax12,0xFE,AA_ALARM_LED,0xEF); */
334 /* printf_P(PSTR("AX12 error %x !\r\n"), err); */
338 for (i=0; i<1; i++) {
341 // pwm_ng_set(&arm.pwm1B, 4095);
354 /* arm_intermediate2(); */
358 // pwm_ng_set(&arm.pwm1B, -4095);
361 // pwm_ng_set(&arm.pwm1B, 0);
368 prog_char str_test_arg0[] = "test";
369 parse_pgm_token_string_t cmd_test_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_test_result, arg0, str_test_arg0);
371 prog_char help_test[] = "Test func";
372 parse_pgm_inst_t cmd_test = {
373 .f = cmd_test_parsed, /* function to call */
374 .data = NULL, /* 2nd arg of func */
375 .help_str = help_test,
376 .tokens = { /* token list, NULL terminated */
377 (prog_void *)&cmd_test_arg0,
382 /**********************************************************/
385 /* this structure is filled when cmd_arm_straight is parsed successfully */
386 struct cmd_arm_straight_result {
390 /* function called when cmd_arm_straight is parsed successfully */
391 static void cmd_arm_straight_parsed(void * parsed_result, void * data)
393 int32_t pos_shoulder[] = {
422 /* vitesse servo : 3ff = 114RPM = 233.2 pas/100ms */
423 int32_t pos_elbow[] = {
454 int32_t speed_shoulder;
457 arm_goto(pos_shoulder[0], pos_elbow[0], 500);
459 while(uart_recv_nowait(0) == -1);
462 for (i=1; i<26; i++) {
463 speed_shoulder = pos_shoulder[i] - pos_shoulder[i-1];
464 speed_shoulder /= 10; /* period is 5ms */
465 if (speed_shoulder < 0)
466 speed_shoulder = -speed_shoulder;
468 speed_elbow = pos_elbow[i] - pos_elbow[i-1];
469 speed_elbow *= 0x3ff;
473 speed_elbow = -speed_elbow;
476 printf("shoulder : %ld, %ld / elbow : %ld, %ld\r\n",
477 pos_shoulder[i], speed_shoulder,
478 pos_elbow[i], speed_elbow);
480 quadramp_set_1st_order_vars(&arm.qr_mot, speed_shoulder, speed_shoulder);
481 cs_set_consign(&arm.cs_mot, pos_shoulder[i]);
483 AX12_write_int(&ax12, ELBOW_AX12, AA_MOVING_SPEED_L, speed_elbow);
484 AX12_write_int(&ax12, ELBOW_AX12, AA_GOAL_POSITION_L, pos_elbow[i]);
491 prog_char str_arm_straight_arg0[] = "arm_straight";
492 parse_pgm_token_string_t cmd_arm_straight_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_arm_straight_result, arg0, str_arm_straight_arg0);
494 prog_char help_arm_straight[] = "Arm_Straight func";
495 parse_pgm_inst_t cmd_arm_straight = {
496 .f = cmd_arm_straight_parsed, /* function to call */
497 .data = NULL, /* 2nd arg of func */
498 .help_str = help_arm_straight,
499 .tokens = { /* token list, NULL terminated */
500 (prog_void *)&cmd_arm_straight_arg0,
505 /**********************************************************/
507 /* this structure is filled when cmd_baudrate is parsed successfully */
508 struct cmd_baudrate_result {
513 /* function called when cmd_baudrate is parsed successfully */
514 static void cmd_baudrate_parsed(void * parsed_result, void * data)
516 struct cmd_baudrate_result *res = parsed_result;
517 struct uart_config c;
519 printf_P(PSTR("%d %d\r\n"), UBRR1H, UBRR1L);
521 c.baudrate = res->arg1;
523 printf_P(PSTR("%d %d\r\n"), UBRR1H, UBRR1L);
526 prog_char str_baudrate_arg0[] = "baudrate";
527 parse_pgm_token_string_t cmd_baudrate_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_baudrate_result, arg0, str_baudrate_arg0);
528 parse_pgm_token_num_t cmd_baudrate_arg1 = TOKEN_NUM_INITIALIZER(struct cmd_baudrate_result, arg1, UINT32);
530 prog_char help_baudrate[] = "Change ax12 baudrate";
531 parse_pgm_inst_t cmd_baudrate = {
532 .f = cmd_baudrate_parsed, /* function to call */
533 .data = NULL, /* 2nd arg of func */
534 .help_str = help_baudrate,
535 .tokens = { /* token list, NULL terminated */
536 (prog_void *)&cmd_baudrate_arg0,
537 (prog_void *)&cmd_baudrate_arg1,
542 /**********************************************************/
544 /* this structure is filled when cmd_arm_goto is parsed successfully */
545 struct cmd_arm_goto_result {
552 /* function called when cmd_arm_goto is parsed successfully */
553 static void cmd_arm_goto_parsed(void * parsed_result, void * data)
555 struct cmd_arm_goto_result *res = parsed_result;
556 arm_goto(res->arg1, res->arg2, res->arg3);
559 prog_char str_arm_goto_arg0[] = "arm_goto";
560 parse_pgm_token_string_t cmd_arm_goto_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_arm_goto_result, arg0, str_arm_goto_arg0);
561 parse_pgm_token_num_t cmd_arm_goto_arg1 = TOKEN_NUM_INITIALIZER(struct cmd_arm_goto_result, arg1, INT32);
562 parse_pgm_token_num_t cmd_arm_goto_arg2 = TOKEN_NUM_INITIALIZER(struct cmd_arm_goto_result, arg2, UINT16);
563 parse_pgm_token_num_t cmd_arm_goto_arg3 = TOKEN_NUM_INITIALIZER(struct cmd_arm_goto_result, arg3, UINT16);
565 prog_char help_arm_goto[] = "Change arm position (shoulder, elbow, wrist)";
566 parse_pgm_inst_t cmd_arm_goto = {
567 .f = cmd_arm_goto_parsed, /* function to call */
568 .data = NULL, /* 2nd arg of func */
569 .help_str = help_arm_goto,
570 .tokens = { /* token list, NULL terminated */
571 (prog_void *)&cmd_arm_goto_arg0,
572 (prog_void *)&cmd_arm_goto_arg1,
573 (prog_void *)&cmd_arm_goto_arg2,
574 (prog_void *)&cmd_arm_goto_arg3,
579 /**********************************************************/
581 /* this structure is filled when cmd_arm_capture is parsed successfully */
582 struct cmd_arm_capture_result {
586 /* function called when cmd_arm_capture is parsed successfully */
587 static void cmd_arm_capture_parsed(void * parsed_result, void * data)
590 uint16_t elbow, wrist;
594 ret |= AX12_read_int(&ax12, ELBOW_AX12, AA_PRESENT_POSITION_L, &elbow);
595 ret |= AX12_read_int(&ax12, WRIST_AX12, AA_PRESENT_POSITION_L, &wrist);
596 shoulder = encoders_microb_get_value((void *)ARM_ENC);
598 printf_P(PSTR("AX12 error %.2x!\r\n"), ret);
599 printf_P(PSTR("%ld %d %d\r\n"), shoulder, elbow, wrist);
603 prog_char str_arm_capture_arg0[] = "arm_capture";
604 parse_pgm_token_string_t cmd_arm_capture_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_arm_capture_result, arg0, str_arm_capture_arg0);
606 prog_char help_arm_capture[] = "Change arm position (shoulder, elbow, wrist)";
607 parse_pgm_inst_t cmd_arm_capture = {
608 .f = cmd_arm_capture_parsed, /* function to call */
609 .data = NULL, /* 2nd arg of func */
610 .help_str = help_arm_capture,
611 .tokens = { /* token list, NULL terminated */
612 (prog_void *)&cmd_arm_capture_arg0,
616 /**********************************************************/
620 /* this structure is filled when cmd_uint16_read is parsed successfully */
621 struct cmd_uint16_result {
628 /* function called when cmd_uint16_read is parsed successfully */
629 static void cmd_uint16_read_parsed(void * parsed_result, void * data)
631 struct cmd_uint16_result *res = parsed_result;
634 uint8_t addr = addr_from_string(res->arg1);
635 ret = AX12_read_int(&ax12, res->num, addr, &val);
637 printf_P(PSTR("AX12 error %.2x!\r\n"), ret);
638 printf_P(PSTR("%s: %d [0x%.4x]\r\n"), res->arg1, val, val);
641 prog_char str_uint16_arg0[] = "read";
642 parse_pgm_token_string_t cmd_uint16_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_uint16_result, arg0, str_uint16_arg0);
643 prog_char str_uint16_arg1[] = "moving_speed#model#goal_pos#cw_angle_limit#ccw_angle_limit#"
644 "max_torque#down_calibration#up_calibration#torque_limit#"
645 "position#speed#load#punch";
646 parse_pgm_token_string_t cmd_uint16_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_uint16_result, arg1, str_uint16_arg1);
647 parse_pgm_token_num_t cmd_uint16_num = TOKEN_NUM_INITIALIZER(struct cmd_uint16_result, num, UINT8);
649 prog_char help_uint16_read[] = "Read uint16 value (type, num)";
650 parse_pgm_inst_t cmd_uint16_read = {
651 .f = cmd_uint16_read_parsed, /* function to call */
652 .data = NULL, /* 2nd arg of func */
653 .help_str = help_uint16_read,
654 .tokens = { /* token list, NULL terminated */
655 (prog_void *)&cmd_uint16_arg0,
656 (prog_void *)&cmd_uint16_arg1,
657 (prog_void *)&cmd_uint16_num,
662 /* function called when cmd_uint16_write is parsed successfully */
663 static void cmd_uint16_write_parsed(void * parsed_result, void * data)
665 struct cmd_uint16_result *res = parsed_result;
667 uint8_t addr = addr_from_string(res->arg1);
668 printf_P(PSTR("writing %s: %d [0x%.4x]\r\n"), res->arg1,
670 ret = AX12_write_int(&ax12, res->num, addr, res->val);
672 printf_P(PSTR("AX12 error %.2x!\r\n"), ret);
675 prog_char str_uint16_arg0_w[] = "write";
676 parse_pgm_token_string_t cmd_uint16_arg0_w = TOKEN_STRING_INITIALIZER(struct cmd_uint16_result, arg0, str_uint16_arg0_w);
677 prog_char str_uint16_arg1_w[] = "moving_speed#goal_pos#cw_angle_limit#ccw_angle_limit#"
678 "max_torque#torque_limit#punch";
679 parse_pgm_token_string_t cmd_uint16_arg1_w = TOKEN_STRING_INITIALIZER(struct cmd_uint16_result, arg1, str_uint16_arg1_w);
680 parse_pgm_token_num_t cmd_uint16_val = TOKEN_NUM_INITIALIZER(struct cmd_uint16_result, val, UINT16);
682 prog_char help_uint16_write[] = "Write uint16 value (write, num, val)";
683 parse_pgm_inst_t cmd_uint16_write = {
684 .f = cmd_uint16_write_parsed, /* function to call */
685 .data = NULL, /* 2nd arg of func */
686 .help_str = help_uint16_write,
687 .tokens = { /* token list, NULL terminated */
688 (prog_void *)&cmd_uint16_arg0_w,
689 (prog_void *)&cmd_uint16_arg1_w,
690 (prog_void *)&cmd_uint16_num,
691 (prog_void *)&cmd_uint16_val,
696 /**********************************************************/
700 /* this structure is filled when cmd_uint8_read is parsed successfully */
701 struct cmd_uint8_result {
708 /* function called when cmd_uint8_read is parsed successfully */
709 static void cmd_uint8_read_parsed(void * parsed_result, void * data)
711 struct cmd_uint8_result *res = parsed_result;
714 uint8_t addr = addr_from_string(res->arg1);
716 ret = AX12_read_byte(&ax12, res->num, addr, &val);
718 printf_P(PSTR("AX12 error %.2x!\r\n"), ret);
719 printf_P(PSTR("%s: %d [0x%.2x]\r\n"), res->arg1, val, val);
722 prog_char str_uint8_arg0[] = "read";
723 parse_pgm_token_string_t cmd_uint8_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_uint8_result, arg0, str_uint8_arg0);
724 prog_char str_uint8_arg1[] = "id#firmware#baudrate#delay#high_lim_temp#"
725 "low_lim_volt#high_lim_volt#status_return#alarm_led#"
726 "alarm_shutdown#torque_enable#led#cw_comp_margin#"
727 "ccw_comp_margin#cw_comp_slope#ccw_comp_slope#"
728 "voltage#temp#reginst#moving#lock";
729 parse_pgm_token_string_t cmd_uint8_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_uint8_result, arg1, str_uint8_arg1);
730 parse_pgm_token_num_t cmd_uint8_num = TOKEN_NUM_INITIALIZER(struct cmd_uint8_result, num, UINT8);
732 prog_char help_uint8_read[] = "Read uint8 value (type, num)";
733 parse_pgm_inst_t cmd_uint8_read = {
734 .f = cmd_uint8_read_parsed, /* function to call */
735 .data = NULL, /* 2nd arg of func */
736 .help_str = help_uint8_read,
737 .tokens = { /* token list, NULL terminated */
738 (prog_void *)&cmd_uint8_arg0,
739 (prog_void *)&cmd_uint8_arg1,
740 (prog_void *)&cmd_uint8_num,
745 /* function called when cmd_uint8_write is parsed successfully */
746 static void cmd_uint8_write_parsed(void * parsed_result, void * data)
748 struct cmd_uint8_result *res = parsed_result;
749 uint8_t addr = addr_from_string(res->arg1);
751 printf_P(PSTR("writing %s: %d [0x%.2x]\r\n"), res->arg1,
753 ret = AX12_write_byte(&ax12, res->num, addr, res->val);
755 printf_P(PSTR("AX12 error %.2x!\r\n"), ret);
758 prog_char str_uint8_arg0_w[] = "write";
759 parse_pgm_token_string_t cmd_uint8_arg0_w = TOKEN_STRING_INITIALIZER(struct cmd_uint8_result, arg0, str_uint8_arg0_w);
760 prog_char str_uint8_arg1_w[] = "id#baudrate#delay#high_lim_temp#"
761 "low_lim_volt#high_lim_volt#status_return#alarm_led#"
762 "alarm_shutdown#torque_enable#led#cw_comp_margin#"
763 "ccw_comp_margin#cw_comp_slope#ccw_comp_slope#"
765 parse_pgm_token_string_t cmd_uint8_arg1_w = TOKEN_STRING_INITIALIZER(struct cmd_uint8_result, arg1, str_uint8_arg1_w);
766 parse_pgm_token_num_t cmd_uint8_val = TOKEN_NUM_INITIALIZER(struct cmd_uint8_result, val, UINT8);
768 prog_char help_uint8_write[] = "Write uint8 value (write, num, val)";
769 parse_pgm_inst_t cmd_uint8_write = {
770 .f = cmd_uint8_write_parsed, /* function to call */
771 .data = NULL, /* 2nd arg of func */
772 .help_str = help_uint8_write,
773 .tokens = { /* token list, NULL terminated */
774 (prog_void *)&cmd_uint8_arg0_w,
775 (prog_void *)&cmd_uint8_arg1_w,
776 (prog_void *)&cmd_uint8_num,
777 (prog_void *)&cmd_uint8_val,
782 /**********************************************************/
785 /* this structure is filled when cmd_encoders is parsed successfully */
786 struct cmd_encoders_result {
791 /* function called when cmd_encoders is parsed successfully */
792 static void cmd_encoders_parsed(void * parsed_result, void * data)
795 while(uart_recv_nowait(0) == -1) {
796 printf_P(PSTR("% .8ld % .8ld % .8ld % .8ld\r\n"),
797 encoders_microb_get_value((void *)0),
798 encoders_microb_get_value((void *)1),
799 encoders_microb_get_value((void *)2),
800 encoders_microb_get_value((void *)3));
806 prog_char str_encoders_arg0[] = "encoders";
807 parse_pgm_token_string_t cmd_encoders_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_encoders_result, arg0, str_encoders_arg0);
808 prog_char str_encoders_arg1[] = "show";
809 parse_pgm_token_string_t cmd_encoders_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_encoders_result, arg1, str_encoders_arg1);
811 prog_char help_encoders[] = "Show encoders values";
812 parse_pgm_inst_t cmd_encoders = {
813 .f = cmd_encoders_parsed, /* function to call */
814 .data = NULL, /* 2nd arg of func */
815 .help_str = help_encoders,
816 .tokens = { /* token list, NULL terminated */
817 (prog_void *)&cmd_encoders_arg0,
818 (prog_void *)&cmd_encoders_arg1,
823 /**********************************************************/
826 /* this structure is filled when cmd_pwm is parsed successfully */
827 struct cmd_pwm_result {
833 /* function called when cmd_pwm is parsed successfully */
834 static void cmd_pwm_parsed(void * parsed_result, void * data)
836 void * pwm_ptr = NULL;
837 struct cmd_pwm_result * res = parsed_result;
839 if (!strcmp_P(res->arg1, PSTR("1(2A)")))
840 pwm_ptr = &arm.pwm1_2A;
841 else if (!strcmp_P(res->arg1, PSTR("2(1A)")))
842 pwm_ptr = &arm.pwm2_1A;
843 else if (!strcmp_P(res->arg1, PSTR("3(1B)")))
844 pwm_ptr = &arm.pwm3_1B;
845 else if (!strcmp_P(res->arg1, PSTR("4(1C)")))
846 pwm_ptr = &arm.pwm4_1C;
848 else if (!strcmp_P(res->arg1, PSTR("s1(3A)")))
849 pwm_ptr = &arm.servo1;
850 else if (!strcmp_P(res->arg1, PSTR("s2(3B)")))
851 pwm_ptr = &arm.servo2;
852 else if (!strcmp_P(res->arg1, PSTR("s3(3C)")))
853 pwm_ptr = &arm.servo3;
854 else if (!strcmp_P(res->arg1, PSTR("s4(5A)")))
855 pwm_ptr = &arm.servo4;
856 else if (!strcmp_P(res->arg1, PSTR("s5(5B)")))
857 pwm_ptr = &arm.servo5;
858 else if (!strcmp_P(res->arg1, PSTR("s6(5C)")))
859 pwm_ptr = &arm.servo6;
862 pwm_ng_set(pwm_ptr, res->arg2);
864 printf_P(PSTR("done\r\n"));
867 prog_char str_pwm_arg0[] = "pwm";
868 parse_pgm_token_string_t cmd_pwm_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_pwm_result, arg0, str_pwm_arg0);
869 prog_char str_pwm_arg1[] = "1(2A)#2(1A)#3(1B)#4(1C)#s1(3A)#s2(3B)#s3(3C)#s4(5A)#s5(5B)#s6(5C)";
870 parse_pgm_token_string_t cmd_pwm_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_pwm_result, arg1, str_pwm_arg1);
871 parse_pgm_token_num_t cmd_pwm_arg2 = TOKEN_NUM_INITIALIZER(struct cmd_pwm_result, arg2, INT16);
873 prog_char help_pwm[] = "Set pwm values [-4096 ; 4095]";
874 parse_pgm_inst_t cmd_pwm = {
875 .f = cmd_pwm_parsed, /* function to call */
876 .data = NULL, /* 2nd arg of func */
877 .help_str = help_pwm,
878 .tokens = { /* token list, NULL terminated */
879 (prog_void *)&cmd_pwm_arg0,
880 (prog_void *)&cmd_pwm_arg1,
881 (prog_void *)&cmd_pwm_arg2,
886 /**********************************************************/
887 /* Gains for control system */
889 /* this structure is filled when cmd_gain is parsed successfully */
890 struct cmd_gain_result {
898 /* function called when cmd_gain is parsed successfully */
899 static void cmd_gain_parsed(void * parsed_result, void * data)
901 struct cmd_gain_result * res = parsed_result;
903 if (!strcmp_P(res->arg1, PSTR("arm"))) {
904 pid_set_gains(&arm.pid_mot, res->p, res->i, res->d);
906 /* else it is a "show" */
908 printf_P(PSTR("arm %d %d %d\r\n"),
909 pid_get_gain_P(&arm.pid_mot),
910 pid_get_gain_I(&arm.pid_mot),
911 pid_get_gain_D(&arm.pid_mot));
914 prog_char str_gain_arg0[] = "gain";
915 parse_pgm_token_string_t cmd_gain_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_gain_result, arg0, str_gain_arg0);
916 prog_char str_gain_arg1[] = "arm";
917 parse_pgm_token_string_t cmd_gain_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_gain_result, arg1, str_gain_arg1);
918 parse_pgm_token_num_t cmd_gain_p = TOKEN_NUM_INITIALIZER(struct cmd_gain_result, p, INT16);
919 parse_pgm_token_num_t cmd_gain_i = TOKEN_NUM_INITIALIZER(struct cmd_gain_result, i, INT16);
920 parse_pgm_token_num_t cmd_gain_d = TOKEN_NUM_INITIALIZER(struct cmd_gain_result, d, INT16);
922 prog_char help_gain[] = "Set gain values for PID";
923 parse_pgm_inst_t cmd_gain = {
924 .f = cmd_gain_parsed, /* function to call */
925 .data = NULL, /* 2nd arg of func */
926 .help_str = help_gain,
927 .tokens = { /* token list, NULL terminated */
928 (prog_void *)&cmd_gain_arg0,
929 (prog_void *)&cmd_gain_arg1,
930 (prog_void *)&cmd_gain_p,
931 (prog_void *)&cmd_gain_i,
932 (prog_void *)&cmd_gain_d,
939 prog_char str_gain_show_arg[] = "show";
940 parse_pgm_token_string_t cmd_gain_show_arg = TOKEN_STRING_INITIALIZER(struct cmd_gain_result, arg1, str_gain_show_arg);
942 prog_char help_gain_show[] = "Show gain values for PID";
943 parse_pgm_inst_t cmd_gain_show = {
944 .f = cmd_gain_parsed, /* function to call */
945 .data = NULL, /* 2nd arg of func */
946 .help_str = help_gain_show,
947 .tokens = { /* token list, NULL terminated */
948 (prog_void *)&cmd_gain_arg0,
949 (prog_void *)&cmd_gain_show_arg,
955 /**********************************************************/
956 /* Speeds for control system */
958 /* this structure is filled when cmd_speed is parsed successfully */
959 struct cmd_speed_result {
965 /* function called when cmd_speed is parsed successfully */
966 static void cmd_speed_parsed(void * parsed_result, void * data)
969 struct cmd_speed_result * res = parsed_result;
971 if (!strcmp_P(res->arg1, PSTR("arm"))) {
972 ramp_set_vars(&ext.r_b, res->s, res->s); /* set speed */
975 printf_P(PSTR("arm %lu\r\n"),
978 printf_P(PSTR("DISABLED FOR NOW\r\n"));
982 prog_char str_speed_arg0[] = "speed";
983 parse_pgm_token_string_t cmd_speed_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_speed_result, arg0, str_speed_arg0);
984 prog_char str_speed_arg1[] = "arm#show";
985 parse_pgm_token_string_t cmd_speed_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_speed_result, arg1, str_speed_arg1);
986 parse_pgm_token_num_t cmd_speed_s = TOKEN_NUM_INITIALIZER(struct cmd_speed_result, s, UINT16);
988 prog_char help_speed[] = "Set speed values for ramp filter";
989 parse_pgm_inst_t cmd_speed = {
990 .f = cmd_speed_parsed, /* function to call */
991 .data = NULL, /* 2nd arg of func */
992 .help_str = help_speed,
993 .tokens = { /* token list, NULL terminated */
994 (prog_void *)&cmd_speed_arg0,
995 (prog_void *)&cmd_speed_arg1,
996 (prog_void *)&cmd_speed_s,
1003 prog_char str_speed_show_arg[] = "show";
1004 parse_pgm_token_string_t cmd_speed_show_arg = TOKEN_STRING_INITIALIZER(struct cmd_speed_result, arg1, str_speed_show_arg);
1006 prog_char help_speed_show[] = "Show speed values for ramp filter";
1007 parse_pgm_inst_t cmd_speed_show = {
1008 .f = cmd_speed_parsed, /* function to call */
1009 .data = NULL, /* 2nd arg of func */
1010 .help_str = help_speed_show,
1011 .tokens = { /* token list, NULL terminated */
1012 (prog_void *)&cmd_speed_arg0,
1013 (prog_void *)&cmd_speed_show_arg,
1019 /**********************************************************/
1020 /* Pos for control system */
1022 /* this structure is filled when cmd_pos is parsed successfully */
1023 struct cmd_pos_result {
1024 fixed_string_t arg0;
1025 fixed_string_t arg1;
1029 /* function called when cmd_pos is parsed successfully */
1030 static void cmd_pos_parsed(void * parsed_result, void * data)
1032 struct cmd_pos_result * res = parsed_result;
1035 if (!strcmp_P(res->arg1, PSTR("arm"))) {
1036 cs_set_consign(&arm.cs_mot, res->p);
1040 for (i=0; i<50; i++) {
1041 printf("%ld %ld %ld\r\n",
1042 pid_get_value_in(&arm.pid_mot),
1043 pid_get_value_out(&arm.pid_mot),
1044 pid_get_value_D(&arm.pid_mot)
1050 prog_char str_pos_arg0[] = "pos";
1051 parse_pgm_token_string_t cmd_pos_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_pos_result, arg0, str_pos_arg0);
1052 prog_char str_pos_arg1[] = "arm";
1053 parse_pgm_token_string_t cmd_pos_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_pos_result, arg1, str_pos_arg1);
1054 parse_pgm_token_num_t cmd_pos_p = TOKEN_NUM_INITIALIZER(struct cmd_pos_result, p, INT32);
1056 prog_char help_pos[] = "Set pos value";
1057 parse_pgm_inst_t cmd_pos = {
1058 .f = cmd_pos_parsed, /* function to call */
1059 .data = NULL, /* 2nd arg of func */
1060 .help_str = help_pos,
1061 .tokens = { /* token list, NULL terminated */
1062 (prog_void *)&cmd_pos_arg0,
1063 (prog_void *)&cmd_pos_arg1,
1064 (prog_void *)&cmd_pos_p,
1070 /**********************************************************/
1073 /* this structure is filled when cmd_event is parsed successfully */
1074 struct cmd_event_result {
1075 fixed_string_t arg0;
1076 fixed_string_t arg1;
1077 fixed_string_t arg2;
1080 /* function called when cmd_event is parsed successfully */
1081 static void cmd_event_parsed(void * parsed_result, void * data)
1086 struct cmd_event_result * res = parsed_result;
1088 if (!strcmp_P(res->arg1, PSTR("cs"))) {
1089 if (!strcmp_P(res->arg2, PSTR("on"))) {
1090 pwm_ng_set(ARM_MOT_PWM, 0);
1091 printf_P(PSTR("ax12 will start\r\n"));
1092 while(uart_recv_nowait(0) == -1);
1093 AX12_write_int(&ax12,0xFE,AA_TORQUE_ENABLE,0x1);
1094 AX12_write_int(&ax12, ELBOW_AX12, AA_GOAL_POSITION_L, 660);
1095 AX12_write_int(&ax12, WRIST_AX12, AA_GOAL_POSITION_L, 613);
1096 printf_P(PSTR("Set the arm to 0\r\n"));
1097 while(uart_recv_nowait(0) == -1);
1098 // encoders_microb_set_value(ARM_ENC, 0);
1102 /* else if (!strcmp_P(res->arg1, PSTR("catapult"))) */
1103 /* bit = CATAPULT_CS_ON; */
1105 if (!strcmp_P(res->arg2, PSTR("on")))
1107 else if (!strcmp_P(res->arg2, PSTR("off")))
1108 arm.flags &= (~bit);
1109 printf_P(PSTR("%s is %s\r\n"), res->arg1,
1110 (bit & arm.flags) ? "on":"off");
1114 prog_char str_event_arg0[] = "event";
1115 parse_pgm_token_string_t cmd_event_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_event_result, arg1, str_event_arg0);
1116 prog_char str_event_arg1[] = "cs";
1117 parse_pgm_token_string_t cmd_event_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_event_result, arg1, str_event_arg1);
1118 prog_char str_event_arg2[] = "on#off#show";
1119 parse_pgm_token_string_t cmd_event_arg2 = TOKEN_STRING_INITIALIZER(struct cmd_event_result, arg2, str_event_arg2);
1121 prog_char help_event[] = "Enable/disable events";
1122 parse_pgm_inst_t cmd_event = {
1123 .f = cmd_event_parsed, /* function to call */
1124 .data = NULL, /* 2nd arg of func */
1125 .help_str = help_event,
1126 .tokens = { /* token list, NULL terminated */
1127 (prog_void *)&cmd_event_arg0,
1128 (prog_void *)&cmd_event_arg1,
1129 (prog_void *)&cmd_event_arg2,
1134 /**********************************************************/
1135 /* Maximums for control system */
1137 /* this structure is filled when cmd_maximum is parsed successfully */
1138 struct cmd_maximum_result {
1139 fixed_string_t arg0;
1140 fixed_string_t arg1;
1146 /* function called when cmd_maximum is parsed successfully */
1147 static void cmd_maximum_parsed(void * parsed_result, void * data)
1149 struct cmd_maximum_result * res = parsed_result;
1151 if (!strcmp_P(res->arg1, PSTR("arm"))) {
1152 pid_set_maximums(&arm.pid_mot, res->in, res->i, res->out);
1154 /* else it is a "show" */
1156 printf_P(PSTR("maximum arm %lu %lu %lu\r\n"),
1157 pid_get_max_in(&arm.pid_mot),
1158 pid_get_max_I(&arm.pid_mot),
1159 pid_get_max_out(&arm.pid_mot));
1162 prog_char str_maximum_arg0[] = "maximum";
1163 parse_pgm_token_string_t cmd_maximum_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_maximum_result, arg0, str_maximum_arg0);
1164 prog_char str_maximum_arg1[] = "arm";
1165 parse_pgm_token_string_t cmd_maximum_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_maximum_result, arg1, str_maximum_arg1);
1166 parse_pgm_token_num_t cmd_maximum_in = TOKEN_NUM_INITIALIZER(struct cmd_maximum_result, in, UINT32);
1167 parse_pgm_token_num_t cmd_maximum_i = TOKEN_NUM_INITIALIZER(struct cmd_maximum_result, i, UINT32);
1168 parse_pgm_token_num_t cmd_maximum_out = TOKEN_NUM_INITIALIZER(struct cmd_maximum_result, out, UINT32);
1170 prog_char help_maximum[] = "Set maximum values for PID (in, I, out)";
1171 parse_pgm_inst_t cmd_maximum = {
1172 .f = cmd_maximum_parsed, /* function to call */
1173 .data = NULL, /* 2nd arg of func */
1174 .help_str = help_maximum,
1175 .tokens = { /* token list, NULL terminated */
1176 (prog_void *)&cmd_maximum_arg0,
1177 (prog_void *)&cmd_maximum_arg1,
1178 (prog_void *)&cmd_maximum_in,
1179 (prog_void *)&cmd_maximum_i,
1180 (prog_void *)&cmd_maximum_out,
1187 prog_char str_maximum_show_arg[] = "show";
1188 parse_pgm_token_string_t cmd_maximum_show_arg = TOKEN_STRING_INITIALIZER(struct cmd_maximum_result, arg1, str_maximum_show_arg);
1190 prog_char help_maximum_show[] = "Show maximum values for PID";
1191 parse_pgm_inst_t cmd_maximum_show = {
1192 .f = cmd_maximum_parsed, /* function to call */
1193 .data = NULL, /* 2nd arg of func */
1194 .help_str = help_maximum_show,
1195 .tokens = { /* token list, NULL terminated */
1196 (prog_void *)&cmd_maximum_arg0,
1197 (prog_void *)&cmd_maximum_show_arg,
1202 /**********************************************************/
1203 /* Quadramp for control system */
1205 /* this structure is filled when cmd_quadramp is parsed successfully */
1206 struct cmd_quadramp_result {
1207 fixed_string_t arg0;
1208 fixed_string_t arg1;
1215 /* function called when cmd_quadramp is parsed successfully */
1216 static void cmd_quadramp_parsed(void * parsed_result, void * data)
1218 struct cmd_quadramp_result * res = parsed_result;
1220 if (!strcmp_P(res->arg1, PSTR("arm"))) {
1221 quadramp_set_1st_order_vars(&arm.qr_mot, res->sp, res->sn);
1222 quadramp_set_2nd_order_vars(&arm.qr_mot, res->ap, res->an);
1224 /* else if (!strcmp_P(res->arg1, PSTR("distance"))) { */
1225 /* quadramp_set_1st_order_vars(&arm.qr_d, res->sp, res->sn); */
1226 /* quadramp_set_2nd_order_vars(&arm.qr_d, res->ap, res->an); */
1228 /* else it's a "show" */
1230 printf_P(PSTR("quadramp arm %ld %ld %ld %ld\r\n"),
1231 arm.qr_mot.var_2nd_ord_pos,
1232 arm.qr_mot.var_2nd_ord_neg,
1233 arm.qr_mot.var_1st_ord_pos,
1234 arm.qr_mot.var_1st_ord_neg);
1237 prog_char str_quadramp_arg0[] = "quadramp";
1238 parse_pgm_token_string_t cmd_quadramp_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_quadramp_result, arg0, str_quadramp_arg0);
1239 prog_char str_quadramp_arg1[] = "arm";
1240 parse_pgm_token_string_t cmd_quadramp_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_quadramp_result, arg1, str_quadramp_arg1);
1241 parse_pgm_token_num_t cmd_quadramp_ap = TOKEN_NUM_INITIALIZER(struct cmd_quadramp_result, ap, UINT32);
1242 parse_pgm_token_num_t cmd_quadramp_an = TOKEN_NUM_INITIALIZER(struct cmd_quadramp_result, an, UINT32);
1243 parse_pgm_token_num_t cmd_quadramp_sp = TOKEN_NUM_INITIALIZER(struct cmd_quadramp_result, sp, UINT32);
1244 parse_pgm_token_num_t cmd_quadramp_sn = TOKEN_NUM_INITIALIZER(struct cmd_quadramp_result, sn, UINT32);
1246 prog_char help_quadramp[] = "Set quadramp values (acc+, acc-, speed+, speed-)";
1247 parse_pgm_inst_t cmd_quadramp = {
1248 .f = cmd_quadramp_parsed, /* function to call */
1249 .data = NULL, /* 2nd arg of func */
1250 .help_str = help_quadramp,
1251 .tokens = { /* token list, NULL terminated */
1252 (prog_void *)&cmd_quadramp_arg0,
1253 (prog_void *)&cmd_quadramp_arg1,
1254 (prog_void *)&cmd_quadramp_ap,
1255 (prog_void *)&cmd_quadramp_an,
1256 (prog_void *)&cmd_quadramp_sp,
1257 (prog_void *)&cmd_quadramp_sn,
1265 prog_char str_quadramp_show_arg[] = "show";
1266 parse_pgm_token_string_t cmd_quadramp_show_arg = TOKEN_STRING_INITIALIZER(struct cmd_quadramp_result, arg1, str_quadramp_show_arg);
1268 prog_char help_quadramp_show[] = "Get quadramp values for control system";
1269 parse_pgm_inst_t cmd_quadramp_show = {
1270 .f = cmd_quadramp_parsed, /* function to call */
1271 .data = NULL, /* 2nd arg of func */
1272 .help_str = help_quadramp_show,
1273 .tokens = { /* token list, NULL terminated */
1274 (prog_void *)&cmd_quadramp_arg0,
1275 (prog_void *)&cmd_quadramp_show_arg,
1281 /**********************************************************/
1285 parse_pgm_ctx_t main_ctx[] = {
1286 (parse_pgm_inst_t *)&cmd_reset,
1287 (parse_pgm_inst_t *)&cmd_spi_test,
1288 (parse_pgm_inst_t *)&cmd_bootloader,
1289 (parse_pgm_inst_t *)&cmd_ax12_stress,
1290 (parse_pgm_inst_t *)&cmd_test,
1291 (parse_pgm_inst_t *)&cmd_arm_straight,
1292 (parse_pgm_inst_t *)&cmd_baudrate,
1293 (parse_pgm_inst_t *)&cmd_arm_goto,
1294 (parse_pgm_inst_t *)&cmd_arm_capture,
1295 (parse_pgm_inst_t *)&cmd_uint16_read,
1296 (parse_pgm_inst_t *)&cmd_uint16_write,
1297 (parse_pgm_inst_t *)&cmd_uint8_read,
1298 (parse_pgm_inst_t *)&cmd_uint8_write,
1299 (parse_pgm_inst_t *)&cmd_encoders,
1300 (parse_pgm_inst_t *)&cmd_pwm,
1301 (parse_pgm_inst_t *)&cmd_gain,
1302 (parse_pgm_inst_t *)&cmd_gain_show,
1303 (parse_pgm_inst_t *)&cmd_speed,
1304 (parse_pgm_inst_t *)&cmd_speed_show,
1305 (parse_pgm_inst_t *)&cmd_pos,
1306 (parse_pgm_inst_t *)&cmd_event,
1307 (parse_pgm_inst_t *)&cmd_maximum,
1308 (parse_pgm_inst_t *)&cmd_maximum_show,
1309 (parse_pgm_inst_t *)&cmd_quadramp,
1310 (parse_pgm_inst_t *)&cmd_quadramp_show,