2 * Copyright (C) 2006-2011 Department of Control Engineering, FEE,
3 * Czech Technical University in Prague, Czech Republic,
4 * http://dce.fel.cvut.cz/
6 * Copyright (C) 2006-2011 Michal Sojka <sojkam1@fel.cvut.cz>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 /* procesor H8S/2638 ver 1.1 */
22 #include <system_def.h>
26 //#include <pxmc_internal.h>
32 #include <periph/sci_rs232.h>
33 #include <periph/sci_channels.h>
42 #include <candriver.h>
43 #include <canOpenDriver.h>
46 #define INLINE /* Empty */
51 * @name Motor control (h8eurobot)
54 /* #define LED_MAIN_LOOP 0 */
55 /* #define LED_CORR_TRIG 2 */
56 /* #define LED_ODO_SEND 3 */
57 #define LED_LIVE 0 /**< D1: Blinks once per second when software is alive */
58 #define LED_CAN_REC 1 /**< D2: Blinks when a CAN message is received:
59 * - 50ms for motion message
60 * - 5ms for other message (corr_trig) */
61 #define LED_ERROR 2 /**< D3: Light = Unhandled exception, Slow blink (4s) = motor error */
62 #define LED_RESET 3 /**< D4: Blinks for 1 s after reset */
66 #define MAX(a,b) ((a)>(b)?(a):(b))
68 bool odometry_triggered = false;
69 unsigned char trig_seq;
71 int cmd_do_quit(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
73 printf("Good bye!\n");
74 *HCAN1_MCR=1; // software reset
79 int cmd_do_canst(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
85 int cmd_do_setflags(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
89 if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG;
91 pxmc_set_flag(mcs,PXMS_PTI_b); // start to updating index pointing to the phase table (ptindx)
92 pxmc_set_flag(mcs,PXMS_PHA_b); // FIXME: is it really need here
93 printf("Flags were set!\n");
97 * Rotates motor slowly four turns forward and than two turns backward
98 * (in a feedforward manner). During movement it displays values read
99 * from HAL sensors and tries to detect correct index mark position.
101 int cmd_do_haltest(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
104 int i, vang, ptindx, ang_deg, dir, rot;
106 int ptmark_errors[10];
107 int err_idx=-1; /* Ignore the first change because */
108 short ptofs = 1; /* it is unlikely that initial offset is 1 (after reset it will be zero) */
109 unsigned last_time = 0;
111 if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG;
113 vang = mcs->pxms_ptvang; /* Remember vang */
116 mcs->pxms_ene=mcs->pxms_me/3;
117 printf("ptindx hal ap ptofs\n");
119 /* schedule adjustment of phase table from index/mark signal */
120 mcs->pxms_cfg |= PXMS_CFG_I2PT_m;
122 /* Move motor to the initial position */
123 mcs->pxms_flg = (PXMS_PHA_m * 0)| PXMS_PTI_m; /* Do not update ptindex acording to HALs */
124 mcs->pxms_ptindx=0; /* Set fixed index to phase tables*/
125 motor_do_output(mcs); /* Apply mag. field accoring to our index */
126 last_time = pxmc_msec_counter;
127 while (pxmc_msec_counter < last_time + 1000) /* Wait for motor to move */
131 for (dir=0; dir<2; dir++) {
132 for (rot=0; rot<4; rot++) {
133 pxmc_initialize(); // reset index mark detection
134 if ((dir&1) == 0) ang_deg=0;
136 while (((dir&1) == 0 && ang_deg < 360) ||
137 ((dir&1) != 0 && ang_deg >= 0)) {
139 ptindx = ((long)ang_deg*mcs->pxms_ptirc/360) % mcs->pxms_ptirc;
142 pxmc_call(mcs, mcs->pxms_do_inp); /* Read IRCs */
143 mcs->pxms_ptindx=ptindx;/* Set fixed index to phase tables*/
144 mcs->pxms_flg = (PXMS_PHA_m * 0) | PXMS_PTI_m; /* Do not update ptindex acording to HALs */
145 motor_do_output(mcs); /* Apply mag. field accoring to our index */
146 last_time = pxmc_msec_counter;
147 while (pxmc_msec_counter < last_time + 4); /* Wait for motor to move */
148 hal = hal_read(mcs); /* read HAL sensors */
149 printf("%d %d %ld %d\n", mcs->pxms_ptindx, hal,
150 mcs->pxms_ap>>PXMC_SUBDIV(mcs), mcs->pxms_ptofs);
151 if (mcs->pxms_ptofs != ptofs) { /* index mark was detected */
152 ptofs = mcs->pxms_ptofs;
153 if ((int)err_idx < (int)(sizeof(ptmark_errors)/sizeof(*ptmark_errors))) {
155 ptmark_errors[err_idx] =
156 mcs->pxms_ptofs + mcs->pxms_ptindx - (mcs->pxms_ap>>PXMC_SUBDIV(mcs));
161 if ((dir&1) == 0) ang_deg++;
167 /* enable adjustment of phase table from index/mark signal */
168 mcs->pxms_cfg |= PXMS_CFG_I2PT_m;
171 mcs->pxms_ptvang = vang;
172 motor_do_output(mcs);
173 mcs->pxms_flg = PXMS_ENI_m;
176 for (i=0; i<err_idx; i++) {
178 printf("ptmark error %d\n", ptmark_errors[i]);
179 avg+=ptmark_errors[i];
181 mcs->pxms_ptmark = (mcs->pxms_ptmark + avg/err_idx) % mcs->pxms_ptirc;
182 printf("pxms_ptmark increased by %ld to %d\n", avg/err_idx, mcs->pxms_ptmark);
187 int cmd_do_setindex(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
190 if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG;
191 int index=atol(param[2]);
192 printf("index=%d\n", index);
193 //printf("No errors detected.\n", index);
194 mcs->pxms_ptindx=index;
198 int cmd_do_setvang(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
201 if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG;
202 int index=atol(param[2]);
203 printf("ptvang=%d\n", index);
204 //printf("No errors detected.\n", index);
205 mcs->pxms_ptvang=index;
210 int cmd_do_setshift(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
213 if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG;
214 int index=atol(param[2]);
215 printf("ptshift=%d\n", index);
216 //printf("No errors detected.\n", index);
217 mcs->pxms_ptshift=index;
221 int cmd_do_showene(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
224 if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG;
225 // if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG;
226 printf("Current ene is: %d\n",mcs->pxms_ene);
227 printf("Current ptindx is: %d\n",mcs->pxms_ptindx);
228 printf("Current ptvang is: %d\n",mcs->pxms_ptvang);
230 printf("Current ptshift is: %d\n",mcs->pxms_ptshift);
231 printf("Current ptofs is: %d\n",mcs->pxms_ptofs);
234 printf("Actual pos is: %ld\n",mcs->pxms_ap>>PXMC_SUBDIV(mcs));
235 printf("Request pos is: %ld\n",mcs->pxms_rp>>PXMC_SUBDIV(mcs));
237 printf("inp_info is: %d\n",*(volatile short*)mcs->pxms_inp_info);
239 //printf("hal is: %d\n", hal_read(mcs) );
241 if((mcs->pxms_flg&PXMS_PTI_m)) printf("PXMS_PTI_m is: enabled\n"); else printf("PXMS_PTI_m is: disabled\n");
242 if((mcs->pxms_flg&PXMS_PHA_m)) printf("PXMS_PHA_m is: enabled\n"); else printf("PXMS_PHA_m is: disabled\n");
246 int cmd_do_nopxmc(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
249 if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG;
250 pxmc_clear_flag(mcs,PXMS_ENR_b);
251 pxmc_clear_flag(mcs,PXMS_ENO_b);
258 int cmd_do_mypwm(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
262 #define _PXMC_MAX_OUT_ 0x6f
263 const unsigned long ph1[6]={2, 1, 1, 0, 1, 1};
264 const unsigned long ph2[6]={1, 0, 1, 1, 2, 1};
265 const unsigned long ph3[6]={1, 1, 2, 1, 1, 0};
266 #undef _PMXC_MAX_OUT_
269 val=atol(param[2])/2;
271 printf("r=%d val=%d\n", r, val);
273 unsigned pwm1=val*ph1[r];
274 unsigned pwm2=val*ph2[r];
275 unsigned pwm3=val*ph3[r];
276 *PWM_PWBFR1A=(pwm1&0x3ff);
277 *PWM_PWBFR1C=(pwm2&0x3ff);
278 *PWM_PWBFR1E=(pwm3&0x3ff);
283 * Implementation of help command with watchdog
285 static INLINE char *skip_white(char *p)
287 while(isspace((__u8)*p)) p++;
292 #define CMD_ARR_STACK_SIZE 4
293 int cmd_do_help_wd(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
297 const cmd_des_t **des_arr=*(const cmd_des_t ***)des->info[0];
298 cmd_des_t const **arr_stack[CMD_ARR_STACK_SIZE];
301 if (cmd_io->priv.ed_line.io_stack)
302 cmd_io = cmd_io->priv.ed_line.io_stack;
305 filt=skip_white(filt);
306 if(!*filt) filt=NULL;
308 cmd_io_puts(cmd_io,"Help for commands\n");
310 wdg_clear(); /* Added to avoid reseting while listing commands */
313 if(!arr_stack_sp) break;
314 des_arr=arr_stack[--arr_stack_sp];
317 if(des==CMD_DES_CONTINUE_AT_ID){
318 /* list continues at new address */
319 des_arr=(const cmd_des_t **)*des_arr;
322 if(des==CMD_DES_INCLUDE_SUBLIST_ID){
323 /* list includes commands from sublists */
324 if(arr_stack_sp>=CMD_ARR_STACK_SIZE){
327 arr_stack[arr_stack_sp++]=des_arr+1;
328 des_arr=(const cmd_des_t **)*des_arr;
333 if(!filt || !strncmp(des->name,filt,strlen(filt))) {
336 cmd_io_puts(cmd_io,des->name);
337 cmd_io_puts(cmd_io," - ");
338 cmd_io_puts(cmd_io,help);
339 cmd_io_puts(cmd_io, "\r\n");
346 /* selection of debug messages */
348 #define DBGPF_AXES 0x00ff /* mask for all axes */
349 #define DBGPF_PER_TIME 0x0100 /* periodic time print */
350 #define DBGPF_PER_POS 0x0800 /* periodic position info */
351 #define DBGPF_CMD_PROC 0x1000 /* command proccessing */
352 unsigned dbg_prt_flg=0;
354 typedef struct dbg_prt_des{
359 const dbg_prt_des_t dbg_prt_des[]={
362 {DBGPF_PER_TIME,"time"},
363 {DBGPF_PER_POS, "pos"},
364 {DBGPF_CMD_PROC,"cmd"},
369 void run_dbg_prt(cmd_io_t *cmd_io)
375 if(dbg_prt_flg & DBGPF_PER_POS) {
376 char reg_ascii_id[4];
381 for(i=0,reg_mask=1;i<pxmc_main_list.pxml_cnt; i++,reg_mask<<=1){
382 if(dbg_prt_flg®_mask&DBGPF_AXES){
383 reg_ascii_id[0]='A'+i;
384 cmd_io_puts(cmd_io,reg_ascii_id);
385 mcs=pxmc_main_list.pxml_arr[i];
386 i2str(s,mcs->pxms_ap>>PXMC_SUBDIV(mcs),8,0);
387 cmd_io_puts(cmd_io,s);
388 cmd_io_puts(cmd_io,mcs->pxms_flg&PXMS_ERR_m?" E":
389 mcs->pxms_flg&PXMS_BSY_m?" B":" -");
391 cmd_io_puts(cmd_io," hal");
392 i2str(s,mcs->pxms_hal,2,0);
393 cmd_io_puts(cmd_io,s);
395 cmd_io_puts(cmd_io,mcs->pxms_flg&PXMS_PHA_m?" A":
396 mcs->pxms_flg&PXMS_PTI_m?" I":" -");
398 cmd_io_puts(cmd_io," i");
399 i2str(s,mcs->pxms_ptindx,4,0);
400 cmd_io_puts(cmd_io,s);
402 cmd_io_puts(cmd_io," o");
403 i2str(s,mcs->pxms_ptofs,6,0);
404 cmd_io_puts(cmd_io,s);
406 cmd_io_puts(cmd_io,"\r\n");
412 int cmd_do_switches(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
416 dbg_prt_des_t *pdes,*pd;
420 pval=(unsigned*)(des->info[0]);
421 pdes=(dbg_prt_des_t*)(des->info[1]);
422 ps=(des->mode&CDESM_OPCHR)?param[3]:param[1];
426 printf(" %s",pdes->name);
436 else if(*ps=='-'){pm_flag=1;ps++;}
438 if(isdigit((uint8_t)*ps)){if(si_long(&ps,&l,0)<0) return -1;}
440 si_alnumn(&ps,str,20);
443 if(!pd->name) return -1;
444 if(!strcmp(pd->name,str)){
457 int cmd_do_pthalign(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
462 if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG;
465 return cmd_opchar_replong(cmd_io, param, (long)mcs->pxms_ptmark, 0, 0);
468 if(*param[2]!=':') return -CMDERR_OPCHAR;
470 res = motor_pthalalign(mcs, 20);
473 return -CMDERR_BADDIO;
479 int runtime_display = 0;
482 cmd_des_t const **cmd_list;
484 /* command descriptions */
485 cmd_des_t const cmd_des_help={0, 0,"HELP","prints help for commands",
486 cmd_do_help_wd,{(char*)&cmd_list}};
487 cmd_des_t const cmd_des_showene={0, 0,"SHOWENE?","shows ene and couple others parameters",
490 cmd_des_t const cmd_des_mypwm={0, 0,"x#","test",
492 cmd_des_t const cmd_des_nopxmc={0, 0,"NOPXMC?","switch of pxmc controller and output",
494 cmd_des_t const cmd_des_disp={0, CDESM_OPCHR|CDESM_RW,"DISP","switch on/off runtime display of variables",
495 cmd_do_rw_int, {(char*)&runtime_display}};
496 cmd_des_t const cmd_des_slowgo={0, CDESM_OPCHR|CDESM_RW,"SLOWGO","program controlled movement",
497 cmd_do_rw_int, {(char*)&slowgo}};
498 cmd_des_t const cmd_des_setindex={0, 0,"SETINDEX?","changes pxms_ptindx",
500 cmd_des_t const cmd_des_setvang={0, 0,"SETVANG?","changes pxms_ptvang",
502 cmd_des_t const cmd_des_halindex={0, 0,"HALTEST?","show hal state with respect to ptindex",
504 cmd_des_t const cmd_des_pthalign={0, CDESM_OPCHR|CDESM_RW,"PTHALIGN?","run alignement of phase according to HAL",
506 cmd_des_t const cmd_des_setshift={0, 0,"SETSHIFT?","changes pxms_ptshift",
508 cmd_des_t const cmd_des_quit={0, 0,"QUIT","exit",
510 cmd_des_t const cmd_des_canst={0, 0,"CANST","Print CAN controller status",
513 cmd_des_t const cmd_des_dprint={0, 0,"dprint","enable debug messages to print, use + - to add remove, list types ?",
515 {(char*)&dbg_prt_flg,(char*)dbg_prt_des}};
517 cmd_des_t const cmd_des_setflags={0, 0,"setflags","set some flags",
521 extern cmd_io_t cmd_io_rs232_line;
522 cmd_des_t const *cmd_list_default[]={
540 (cmd_des_t*)cmd_stm_default,
544 cmd_des_t const **cmd_list=cmd_list_default; /*cmd prikazy pro PC*/
547 void unhandled_exception(void) __attribute__ ((interrupt_handler));
548 void unhandled_exception(void)
551 DEB_LED_ON(LED_ERROR);
553 DEB_LED_OFF(LED_ERROR);
558 void print_mcs_err(pxmc_state_t *mcs, char *name)
560 const char *errmsg[] = {
561 [PXMS_E_COMM&0xff] = "COMM",
562 [PXMS_E_MAXPD&0xff] = "MAXPD",
563 [PXMS_E_OVERL&0xff] = "OVERL",
564 [PXMS_E_HAL&0xff] = "HAL",
565 [PXMS_E_POWER_STAGE&0xff] = "POWER"};
566 printf("PXMC ERROR: %s - %s\n", name, errmsg[mcs->pxms_errno&0xff]);
571 #define ODOMETRY_TABLE_SIZE 10
572 struct odometryData_t
576 } oddata[ODOMETRY_TABLE_SIZE];
579 static INLINE short sendOdometry()
581 static short idxSend=0;
582 static short prevIdxRecive=0xff;
584 if(prevIdxRecive==idxRecive)
586 // Re-send can frames.
590 prevIdxRecive=idxRecive;
591 // Here should be function to send.
599 static INLINE void blink_odo_send(void)
603 if (led) DEB_LED_ON(LED_ODO_SEND);
604 else DEB_LED_OFF(LED_ODO_SEND);
610 * Sends only pxms_ap. Odometry is calculated elsewhere and since we
611 * don't send differences, sequence numbers are not necessary.
613 static INLINE void sendOdometrySimple()
615 /* If the variable is static, it is initialized to zero, so we don't have to initialize it all the time again. */
619 lap = mcs_left.pxms_ap;
620 rap = mcs_right.pxms_ap;
624 m.cob_id.w = CAN_MOTION_ODOMETRY_SIMPLE;
626 /* Data in big-endian, the least significant byte is always zero -
627 * we don't send it */
628 memcpy(&m.data[0], &lap, sizeof(lap)-1);
629 memcpy(&m.data[3], &rap, sizeof(lap)-1);
630 m.data[6] = trig_seq;
631 canMsgTransmit(0, m);
635 static INLINE short storeOdometryInTable()
637 /*FIXME: add detection of error when idxStore>idxRecive.*/
638 oddata[idxStore].dx=x;
639 oddata[idxStore].dy=y;
640 oddata[idxStore].angle=alfa;
641 // Start to count from zero ;)
644 idxStore%=ODOMETRY_TABLE_SIZE;
651 static INLINE void blink_err_led(void)
654 static bool err_led = false;
656 if (err_led) DEB_LED_ON(LED_ERROR);
657 else DEB_LED_OFF(LED_ERROR);
661 static inline bool recoverable_error(pxmc_state_t *mcs)
663 return (mcs->pxms_flg &PXMS_ERR_m &&
664 (mcs->pxms_errno == PXMS_E_MAXPD ||
665 mcs->pxms_errno == PXMS_E_OVERL));
668 static INLINE void handle_motor_errors() {
669 static unsigned last_msg_time=0;
673 if (mcs_left.pxms_flg&PXMS_ERR_m||mcs_right.pxms_flg&PXMS_ERR_m) {
674 pxmc_stop(&mcs_left, 0);
675 pxmc_stop(&mcs_right, 0);
676 if (pxmc_msec_counter - last_msg_time >= 2000) {
678 last_msg_time = pxmc_msec_counter;
679 if (mcs_left.pxms_flg&PXMS_ERR_m) print_mcs_err(&mcs_left, "L");
680 if (mcs_right.pxms_flg&PXMS_ERR_m) print_mcs_err(&mcs_right, "R");
683 /* In case of PXMS_E_MAXPD or PXMS_E_OVERL, we wait 3 seconds and then purge the error. */
684 if (recoverable_error(&mcs_left) ||
685 recoverable_error(&mcs_right)) {
686 static unsigned last_err_time=0;
687 if (last_err_time == 0)
688 last_err_time = pxmc_msec_counter;
689 if (last_err_time != 0 && (pxmc_msec_counter - last_err_time > 3000)) {
690 pxmc_for_each_mcs(i, mcs) {
691 if (recoverable_error(mcs)) {
692 pxmc_set_const_out(mcs,0);
693 pxmc_clear_flag(mcs,PXMS_ERR_b);
702 void led_can_rec(unsigned duration_msec)
705 static unsigned last_rec;
706 static unsigned duration;
708 last_rec = pxmc_msec_counter;
709 duration = MAX(duration_msec, duration);
710 DEB_LED_ON(LED_CAN_REC);
712 if (pxmc_msec_counter - last_rec > duration) {
714 DEB_LED_OFF(LED_CAN_REC);
720 static INLINE void blink_corr_trig(void)
724 if (led) DEB_LED_ON(LED_CORR_TRIG);
725 else DEB_LED_OFF(LED_CORR_TRIG);
731 static INLINE void handle_can_receive(void)
735 while (f_can_receive(0, &msg_rcv)) {
736 switch (msg_rcv.cob_id.w) {
737 case CAN_MOTION_CMD: {
738 short spd_left, spd_right;
739 spd_left = (msg_rcv.data[0] << 8) | msg_rcv.data[1];
740 spd_right= (msg_rcv.data[2] << 8) | msg_rcv.data[3];
742 pxmc_spd(&mcs_left, -spd_left, pxmc_sfikhz*1000 /*timeout in sampling periods = 0.5ms*/);
743 pxmc_spd(&mcs_right,+spd_right, pxmc_sfikhz*1000);
744 /* printf("Left motor speed command: %08x\n",spd_left); */
745 /* printf("Right motor speed command: %08x\n",spd_right); */
750 case CAN_MOTION_RESET: {
751 unsigned now = pxmc_msec_counter;
752 wdg_enable(0); /* 25 us */
753 while (pxmc_msec_counter - now < 10);
754 /* Hopefully, we are reset now. */
763 /* printf("Received message: id=%lx\n", msg_rcv.cob_id.w); */
764 /* for (i = 0 ; i < 8; i++) printf("%02x ", msg_rcv.data[i]); */
770 static INLINE void handle_odometry_send()
772 #define ODOMETRY_PERIOD 43
773 #define ODOMETRY_TIMEOUT (3*ODOMETRY_PERIOD)
775 timeout = ODOMETRY_TIMEOUT,
778 if (odometry_triggered) {
779 odometry_triggered = false;
780 last_send_time = pxmc_msec_counter;
781 sendOdometrySimple();
782 timeout = ODOMETRY_TIMEOUT;
785 if (pxmc_msec_counter - last_send_time >= timeout) {
786 last_send_time = pxmc_msec_counter;
787 sendOdometrySimple();
788 timeout = ODOMETRY_PERIOD;
792 static INLINE void handle_status_send()
794 static unsigned last_send_time=0;
797 if (pxmc_msec_counter - last_send_time >= 500) {
798 last_send_time = pxmc_msec_counter;
799 memset(&m, 0, sizeof(m));
800 m.cob_id.w = CAN_MOTION_STATUS;
802 m.data[0] = mcs_left.pxms_flg & PXMS_ERR_m ? mcs_left.pxms_errno >> 8 : 0;
803 m.data[1] = mcs_left.pxms_flg & PXMS_ERR_m ? mcs_left.pxms_errno & 0xff : 0;
804 m.data[2] = mcs_right.pxms_flg & PXMS_ERR_m ? mcs_right.pxms_errno >> 8 : 0;
805 m.data[3] = mcs_right.pxms_flg & PXMS_ERR_m ? mcs_right.pxms_errno & 0xff : 0;
806 canMsgTransmit(0, m);
810 static INLINE void blink_main_loop()
813 static bool led = false;
815 if (led) DEB_LED_ON(LED_MAIN_LOOP);
816 else DEB_LED_OFF(LED_MAIN_LOOP);
821 static INLINE void handle_leds()
824 static unsigned last=0;
825 static bool on=false;
826 if (pxmc_msec_counter-last >= PERIOD/2) {
831 DEB_LED_ON(LED_LIVE);
835 DEB_LED_OFF(LED_LIVE);
838 DEB_LED_OFF(LED_RESET);
848 void _print(char *ptr);
851 int dbg_prt_last_msec;
854 excptvec_initfill(unhandled_exception, 0);
855 sci_rs232_setmode(19200, 0, 0, sci_rs232_chan_default); //PC
856 DEB_LED_ON(LED_RESET);
857 wdg_enable(6); /* 420 ms */
861 _print("CPU initialized\r\n\r\n");
863 printf("Eurobot motor control application.\n"
864 "Copyright (C) 2005-2011 PiKRON s.r.o., P. Pisa, M. Sojka and others.\n"
865 "This is free software; see the source code for copying conditions.\n"
866 "There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or\n"
867 "FITNESS FOR A PARTICULAR PURPOSE.\n\n");
870 printf("PXMC initialized (motor: %s)", pxmc_variant);
873 pxmc_set_const_out(&mcs_left,0);
874 pxmc_set_const_out(&mcs_right,0);
876 int32_t receive_id[] = { CAN_MOTION_CMD, CAN_MOTION_RESET, -1 };
877 canInit(0, 1000000, receive_id);
878 printf("CAN initialized\n");
880 dbg_prt_last_msec = pxmc_msec_counter;
886 handle_can_receive();
887 handle_odometry_send();
888 handle_status_send();
889 handle_motor_errors();
891 res = cmd_processor_run(&cmd_io_rs232_line, cmd_list_default); // run command processor on serial line
893 if(!res && ((int)(pxmc_msec_counter - dbg_prt_last_msec) > 2000) &&
894 !cmd_io_rs232_line.priv.ed_line.in->lastch) {
895 cmd_io_t *cmd_io = &cmd_io_rs232_line;
896 dbg_prt_last_msec = pxmc_msec_counter;
898 if (cmd_io->priv.ed_line.io_stack)
899 cmd_io = cmd_io->priv.ed_line.io_stack;
905 if (runtime_display) {
906 //printf("c=%d idx=%d\n", test_counter, test_index);
907 //printf("ene=%d\n", mcs_left.pxms_ene);
908 //printf("rs=%ld as=%ld\n", mcs_left.pxms_rs, mcs_left.pxms_as);