config: add support of attiny45
[aversive.git] / projects / microb2010 / mainboard / commands_ax12.c
1 /*
2  *  Copyright Droids Corporation (2009)
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_ax12.c,v 1.3 2009-05-02 10:08:09 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 <ax12.h>
31 #include <uart.h>
32 #include <pwm_ng.h>
33 #include <clock_time.h>
34
35 #include <pid.h>
36 #include <quadramp.h>
37 #include <control_system_manager.h>
38 #include <trajectory_manager.h>
39 #include <vect_base.h>
40 #include <lines.h>
41 #include <polygon.h>
42 #include <obstacle_avoidance.h>
43 #include <blocking_detection_manager.h>
44 #include <robot_system.h>
45 #include <position_manager.h>
46
47 #include <rdline.h>
48 #include <parse.h>
49 #include <parse_string.h>
50 #include <parse_num.h>
51
52 #include "main.h"
53
54 uint8_t addr_from_string(const char *s)
55 {
56         /* 16 bits */
57         if (!strcmp_P(s, PSTR("cw_angle_limit")))
58                 return AA_CW_ANGLE_LIMIT_L;
59         if (!strcmp_P(s, PSTR("ccw_angle_limit")))
60                 return AA_CCW_ANGLE_LIMIT_L;
61         if (!strcmp_P(s, PSTR("max_torque")))
62                 return AA_MAX_TORQUE_L;
63         if (!strcmp_P(s, PSTR("down_calibration")))
64                 return AA_DOWN_CALIBRATION_L;
65         if (!strcmp_P(s, PSTR("up_calibration")))
66                 return AA_UP_CALIBRATION_L;
67         if (!strcmp_P(s, PSTR("torque_limit")))
68                 return AA_TORQUE_LIMIT_L;
69         if (!strcmp_P(s, PSTR("position")))
70                 return AA_PRESENT_POSITION_L;
71         if (!strcmp_P(s, PSTR("speed")))
72                 return AA_PRESENT_SPEED_L;
73         if (!strcmp_P(s, PSTR("load")))
74                 return AA_PRESENT_LOAD_L;
75         if (!strcmp_P(s, PSTR("moving_speed")))
76                 return AA_MOVING_SPEED_L;
77         if (!strcmp_P(s, PSTR("model")))
78                 return AA_MODEL_NUMBER_L;
79         if (!strcmp_P(s, PSTR("goal_pos")))
80                 return AA_GOAL_POSITION_L;
81         if (!strcmp_P(s, PSTR("punch")))
82                 return AA_PUNCH_L;
83
84         /* 8 bits */
85         if (!strcmp_P(s, PSTR("firmware")))
86                 return AA_FIRMWARE;
87         if (!strcmp_P(s, PSTR("id")))
88                 return AA_ID;
89         if (!strcmp_P(s, PSTR("baudrate")))
90                 return AA_BAUD_RATE;
91         if (!strcmp_P(s, PSTR("delay")))
92                 return AA_DELAY_TIME;
93         if (!strcmp_P(s, PSTR("high_lim_temp")))
94                 return AA_HIGHEST_LIMIT_TEMP;
95         if (!strcmp_P(s, PSTR("low_lim_volt")))
96                 return AA_LOWEST_LIMIT_VOLTAGE;
97         if (!strcmp_P(s, PSTR("high_lim_volt")))
98                 return AA_HIGHEST_LIMIT_VOLTAGE;
99         if (!strcmp_P(s, PSTR("status_return")))
100                 return AA_STATUS_RETURN_LEVEL;
101         if (!strcmp_P(s, PSTR("alarm_led")))
102                 return AA_ALARM_LED;
103         if (!strcmp_P(s, PSTR("alarm_shutdown")))
104                 return AA_ALARM_SHUTDOWN;
105         if (!strcmp_P(s, PSTR("torque_enable")))
106                 return AA_TORQUE_ENABLE;
107         if (!strcmp_P(s, PSTR("led")))
108                 return AA_LED;
109         if (!strcmp_P(s, PSTR("cw_comp_margin")))
110                 return AA_CW_COMPLIANCE_MARGIN;
111         if (!strcmp_P(s, PSTR("ccw_comp_margin")))
112                 return AA_CCW_COMPLIANCE_MARGIN;
113         if (!strcmp_P(s, PSTR("cw_comp_slope")))
114                 return AA_CW_COMPLIANCE_SLOPE;
115         if (!strcmp_P(s, PSTR("ccw_comp_slope")))
116                 return AA_CCW_COMPLIANCE_SLOPE;
117         if (!strcmp_P(s, PSTR("voltage")))
118                 return AA_PRESENT_VOLTAGE;
119         if (!strcmp_P(s, PSTR("temp")))
120                 return AA_PRESENT_TEMP;
121         if (!strcmp_P(s, PSTR("reginst")))
122                 return AA_PRESENT_REGINST;
123         if (!strcmp_P(s, PSTR("moving")))
124                 return AA_MOVING;
125         if (!strcmp_P(s, PSTR("lock")))
126                 return AA_LOCK;
127         
128         return 0;
129 }
130
131 /**********************************************************/
132 /* Ax12_Stress */
133
134 /* this structure is filled when cmd_ax12_stress is parsed successfully */
135 struct cmd_ax12_stress_result {
136         fixed_string_t arg0;
137         uint8_t id;
138 };
139
140 /* function called when cmd_ax12_stress is parsed successfully */
141 static void cmd_ax12_stress_parsed(void *parsed_result, void *data)
142 {
143         struct cmd_ax12_stress_result *res = parsed_result;
144         int i, nb_errs = 0;
145         uint8_t val;
146         microseconds t = time_get_us2();
147
148         for (i=0; i<1000; i++) {
149                 if (AX12_read_byte(&gen.ax12, res->id, AA_ID, &val) != 0)
150                         nb_errs ++;
151         }
152
153         printf_P(PSTR("%d errors / 1000\r\n"), nb_errs);
154         t = (time_get_us2() - t) / 1000;
155         printf_P(PSTR("Test done in %d ms\r\n"), (int)t);
156 }
157
158 prog_char str_ax12_stress_arg0[] = "ax12_stress";
159 parse_pgm_token_string_t cmd_ax12_stress_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_ax12_stress_result, arg0, str_ax12_stress_arg0);
160 parse_pgm_token_num_t cmd_ax12_stress_id = TOKEN_NUM_INITIALIZER(struct cmd_ax12_stress_result, id, UINT8);
161
162 prog_char help_ax12_stress[] = "Stress an AX12 with 1000 'read id' commands";
163 parse_pgm_inst_t cmd_ax12_stress = {
164         .f = cmd_ax12_stress_parsed,  /* function to call */
165         .data = NULL,      /* 2nd arg of func */
166         .help_str = help_ax12_stress,
167         .tokens = {        /* token list, NULL terminated */
168                 (prog_void *)&cmd_ax12_stress_arg0, 
169                 (prog_void *)&cmd_ax12_stress_id, 
170                 NULL,
171         },
172 };
173
174 /**********************************************************/
175
176 /* this structure is filled when cmd_baudrate is parsed successfully */
177 struct cmd_baudrate_result {
178         fixed_string_t arg0;
179         uint32_t arg1;
180 };
181
182 /* function called when cmd_baudrate is parsed successfully */
183 static void cmd_baudrate_parsed(void * parsed_result, void * data)
184 {
185 #ifdef HOST_VERSION
186         printf("not implemented\n");
187 #else
188         struct cmd_baudrate_result *res = parsed_result;
189         struct uart_config c;
190
191         printf_P(PSTR("%d %d\r\n"), UBRR1H, UBRR1L);
192         uart_getconf(1, &c);
193         c.baudrate = res->arg1;
194         uart_setconf(1, &c);
195         printf_P(PSTR("%d %d\r\n"), UBRR1H, UBRR1L);
196 #endif
197 }
198
199 prog_char str_baudrate_arg0[] = "baudrate";
200 parse_pgm_token_string_t cmd_baudrate_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_baudrate_result, arg0, str_baudrate_arg0);
201 parse_pgm_token_num_t cmd_baudrate_arg1 = TOKEN_NUM_INITIALIZER(struct cmd_baudrate_result, arg1, UINT32);
202
203 prog_char help_baudrate[] = "Change ax12 baudrate";
204 parse_pgm_inst_t cmd_baudrate = {
205         .f = cmd_baudrate_parsed,  /* function to call */
206         .data = NULL,      /* 2nd arg of func */
207         .help_str = help_baudrate,
208         .tokens = {        /* token list, NULL terminated */
209                 (prog_void *)&cmd_baudrate_arg0, 
210                 (prog_void *)&cmd_baudrate_arg1, 
211                 NULL,
212         },
213 };
214
215 /**********************************************************/
216 /* Uint16 */
217
218
219 /* this structure is filled when cmd_uint16_read is parsed successfully */
220 struct cmd_uint16_result {
221         fixed_string_t arg0;
222         fixed_string_t arg1;
223         uint8_t num;
224         uint16_t val;
225 };
226
227 /* function called when cmd_uint16_read is parsed successfully */
228 static void cmd_uint16_read_parsed(void * parsed_result, void * data)
229 {
230         struct cmd_uint16_result *res = parsed_result;
231         uint8_t ret;
232         uint16_t val;
233         uint8_t addr = addr_from_string(res->arg1);
234         ret = AX12_read_int(&gen.ax12, res->num, addr, &val);
235         if (ret)
236                 printf_P(PSTR("AX12 error %.2x!\r\n"), ret);
237         printf_P(PSTR("%s: %d [0x%.4x]\r\n"), res->arg1, val, val);
238 }
239
240 prog_char str_uint16_arg0[] = "read";
241 parse_pgm_token_string_t cmd_uint16_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_uint16_result, arg0, str_uint16_arg0);
242 prog_char str_uint16_arg1[] = "moving_speed#model#goal_pos#cw_angle_limit#ccw_angle_limit#"
243                 "max_torque#down_calibration#up_calibration#torque_limit#"
244                 "position#speed#load#punch";
245 parse_pgm_token_string_t cmd_uint16_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_uint16_result, arg1, str_uint16_arg1);
246 parse_pgm_token_num_t cmd_uint16_num = TOKEN_NUM_INITIALIZER(struct cmd_uint16_result, num, UINT8);
247
248 prog_char help_uint16_read[] = "Read uint16 value (type, num)";
249 parse_pgm_inst_t cmd_uint16_read = {
250         .f = cmd_uint16_read_parsed,  /* function to call */
251         .data = NULL,      /* 2nd arg of func */
252         .help_str = help_uint16_read,
253         .tokens = {        /* token list, NULL terminated */
254                 (prog_void *)&cmd_uint16_arg0,
255                 (prog_void *)&cmd_uint16_arg1,
256                 (prog_void *)&cmd_uint16_num,
257                 NULL,
258         },
259 };
260
261 /* function called when cmd_uint16_write is parsed successfully */
262 static void cmd_uint16_write_parsed(void * parsed_result, void * data)
263 {
264         struct cmd_uint16_result *res = parsed_result;
265         uint8_t ret;
266         uint8_t addr = addr_from_string(res->arg1);
267         printf_P(PSTR("writing %s: %d [0x%.4x]\r\n"), res->arg1,
268                  res->val, res->val);
269         ret = AX12_write_int(&gen.ax12, res->num, addr, res->val);
270         if (ret)
271                 printf_P(PSTR("AX12 error %.2x!\r\n"), ret);
272 }
273
274 prog_char str_uint16_arg0_w[] = "write";
275 parse_pgm_token_string_t cmd_uint16_arg0_w = TOKEN_STRING_INITIALIZER(struct cmd_uint16_result, arg0, str_uint16_arg0_w);
276 prog_char str_uint16_arg1_w[] = "moving_speed#goal_pos#cw_angle_limit#ccw_angle_limit#"
277                 "max_torque#torque_limit#punch";
278 parse_pgm_token_string_t cmd_uint16_arg1_w = TOKEN_STRING_INITIALIZER(struct cmd_uint16_result, arg1, str_uint16_arg1_w);
279 parse_pgm_token_num_t cmd_uint16_val = TOKEN_NUM_INITIALIZER(struct cmd_uint16_result, val, UINT16);
280
281 prog_char help_uint16_write[] = "Write uint16 value (write, num, val)";
282 parse_pgm_inst_t cmd_uint16_write = {
283         .f = cmd_uint16_write_parsed,  /* function to call */
284         .data = NULL,      /* 2nd arg of func */
285         .help_str = help_uint16_write,
286         .tokens = {        /* token list, NULL terminated */
287                 (prog_void *)&cmd_uint16_arg0_w,
288                 (prog_void *)&cmd_uint16_arg1_w,
289                 (prog_void *)&cmd_uint16_num,
290                 (prog_void *)&cmd_uint16_val,
291                 NULL,
292         },
293 };
294
295 /**********************************************************/
296 /* Uint8 */
297
298
299 /* this structure is filled when cmd_uint8_read is parsed successfully */
300 struct cmd_uint8_result {
301         fixed_string_t arg0;
302         fixed_string_t arg1;
303         uint8_t num;
304         uint8_t val;
305 };
306
307 /* function called when cmd_uint8_read is parsed successfully */
308 static void cmd_uint8_read_parsed(void * parsed_result, void * data)
309 {
310         struct cmd_uint8_result *res = parsed_result;
311         uint8_t ret;
312         uint8_t val;
313         uint8_t addr = addr_from_string(res->arg1);
314
315         ret = AX12_read_byte(&gen.ax12, res->num, addr, &val);
316         if (ret)
317                 printf_P(PSTR("AX12 error %.2x!\r\n"), ret);
318         printf_P(PSTR("%s: %d [0x%.2x]\r\n"), res->arg1, val, val);
319 }
320
321 prog_char str_uint8_arg0[] = "read";
322 parse_pgm_token_string_t cmd_uint8_arg0 = TOKEN_STRING_INITIALIZER(struct cmd_uint8_result, arg0, str_uint8_arg0);
323 prog_char str_uint8_arg1[] = "id#firmware#baudrate#delay#high_lim_temp#"
324                 "low_lim_volt#high_lim_volt#status_return#alarm_led#"
325                 "alarm_shutdown#torque_enable#led#cw_comp_margin#"
326                 "ccw_comp_margin#cw_comp_slope#ccw_comp_slope#"
327                 "voltage#temp#reginst#moving#lock";
328 parse_pgm_token_string_t cmd_uint8_arg1 = TOKEN_STRING_INITIALIZER(struct cmd_uint8_result, arg1, str_uint8_arg1);
329 parse_pgm_token_num_t cmd_uint8_num = TOKEN_NUM_INITIALIZER(struct cmd_uint8_result, num, UINT8);
330
331 prog_char help_uint8_read[] = "Read uint8 value (type, num)";
332 parse_pgm_inst_t cmd_uint8_read = {
333         .f = cmd_uint8_read_parsed,  /* function to call */
334         .data = NULL,      /* 2nd arg of func */
335         .help_str = help_uint8_read,
336         .tokens = {        /* token list, NULL terminated */
337                 (prog_void *)&cmd_uint8_arg0,
338                 (prog_void *)&cmd_uint8_arg1,
339                 (prog_void *)&cmd_uint8_num,
340                 NULL,
341         },
342 };
343
344 /* function called when cmd_uint8_write is parsed successfully */
345 static void cmd_uint8_write_parsed(void * parsed_result, void * data)
346 {
347         struct cmd_uint8_result *res = parsed_result;
348         uint8_t addr = addr_from_string(res->arg1);
349         uint8_t ret;
350         printf_P(PSTR("writing %s: %d [0x%.2x]\r\n"), res->arg1, 
351                  res->val, res->val);
352         ret = AX12_write_byte(&gen.ax12, res->num, addr, res->val);
353         if (ret)
354                 printf_P(PSTR("AX12 error %.2x!\r\n"), ret);
355 }
356
357 prog_char str_uint8_arg0_w[] = "write";
358 parse_pgm_token_string_t cmd_uint8_arg0_w = TOKEN_STRING_INITIALIZER(struct cmd_uint8_result, arg0, str_uint8_arg0_w);
359 prog_char str_uint8_arg1_w[] = "id#baudrate#delay#high_lim_temp#"
360                 "low_lim_volt#high_lim_volt#status_return#alarm_led#"
361                 "alarm_shutdown#torque_enable#led#cw_comp_margin#"
362                 "ccw_comp_margin#cw_comp_slope#ccw_comp_slope#"
363                 "reginst#lock";
364 parse_pgm_token_string_t cmd_uint8_arg1_w = TOKEN_STRING_INITIALIZER(struct cmd_uint8_result, arg1, str_uint8_arg1_w);
365 parse_pgm_token_num_t cmd_uint8_val = TOKEN_NUM_INITIALIZER(struct cmd_uint8_result, val, UINT8);
366
367 prog_char help_uint8_write[] = "Write uint8 value (write, num, val)";
368 parse_pgm_inst_t cmd_uint8_write = {
369         .f = cmd_uint8_write_parsed,  /* function to call */
370         .data = NULL,      /* 2nd arg of func */
371         .help_str = help_uint8_write,
372         .tokens = {        /* token list, NULL terminated */
373                 (prog_void *)&cmd_uint8_arg0_w,
374                 (prog_void *)&cmd_uint8_arg1_w,
375                 (prog_void *)&cmd_uint8_num,
376                 (prog_void *)&cmd_uint8_val,
377                 NULL,
378         },
379 };