6 * @author Bc. Jiri Kubias, jiri.kubias@gmail.com
7 * @author Michal Sojka <sojkam1@fel.cvut.cz>
14 * @defgroup fork Vidle (fork) application
22 #include <lpc21xx.h> /* LPC21xx definitions */
25 #include <system_def.h>
27 #include <periph/can.h>
32 #include <can_msg_def.h>
37 #include <expansion.h>
39 #define CAN_SPEED 1000000 //< CAN bus speed
42 #define START_SEND_PRIOD_FAST 50 /* [miliseconds] */
43 #define START_SEND_PRIOD_SLOW 300 /* [miliseconds] */
44 #define START_SEND_FAST_COUNT 10 /* How many times to send start with small period (after a change) */
47 #define CL_SENSOR_IN 16 //port for sending command to color sensor(via power switch)
52 #define TIMER_IRQ_PRIORITY 5
54 #define BUMPER_LEFT GPIOPORT_8
55 #define BUMPER_RIGHT GPIOPORT_6
57 #define BUMPER_LEFT_ACROSS GPIOPORT_3
58 #define BUMPER_RIGHT_ACROSS GPIOPORT_1
60 #define CL_SENSOR_OUT/*BUMPER_REAR_LEFT*/ GPIOPORT_7 //port for receiving data from color sensor used to be BUMPER_REAR_LEFT
61 #define BUMPER_REAR GPIOPORT_4
63 #define COLOR_PIN0 EXPPORT_4
64 #define COLOR_PIN1 EXPPORT_5
65 #define SWITCH_STRATEGY_PIN EXPPORT_8
66 #define START_PIN EXPPORT_7
67 #define SWITCH_HOME_PIN EXPPORT_6
70 struct fsm fsm_jaw_right;
71 struct fsm fsm_jaw_left;
72 int32_t cl_sensor_timer;
73 int32_t cl_sensor_refresh;
77 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
78 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
79 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
81 void init_motors(void){
83 init_engine_A(); // initialization of PWM unit
84 engine_A_en(ENGINE_EN_ON); //enable motor A
85 engine_A_dir(ENGINE_DIR_FW); //set direction
86 engine_A_pwm(0); // STOP pwm is in percent, range 0~100~200
88 init_engine_B(); // initialization of PWM unit
89 engine_B_en(ENGINE_EN_ON); //enable motor A
90 engine_B_dir(ENGINE_DIR_FW); //set direction
91 engine_B_pwm(0); // STOP pwm is in percent, range 0~100~200
96 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97 void set_irq_handler(uint8_t source, uint8_t irq_vect, void (*handler)()) {
98 /* set interrupt vector */
99 ((uint32_t*)&VICVectAddr0)[irq_vect] = (uint32_t)handler;
100 ((uint32_t*)&VICVectCntl0)[irq_vect] = 0x20 | source;
101 /* enable interrupt */
102 VICIntEnable = 1<<source;
105 void start_button(void)
108 bool start_condition;
109 static bool last_start_condition = 0;
111 static int count = 0;
112 static uint32_t next_send = 0;
115 start_condition = (IO0PIN & (1<<START_PIN)) == 0;
117 if (start_condition != last_start_condition) {
120 last_start_condition = start_condition;
122 next_send = timer_msec; /* Send now */
126 if (timer_msec >= next_send) {
127 msg.id = CAN_ROBOT_CMD;
130 msg.data[0] = start_condition;
132 // send_rs_str("start\n");
134 /*while*/ (can_tx_msg(&msg));
136 if (count < START_SEND_FAST_COUNT) {
138 next_send = timer_msec + START_SEND_PRIOD_FAST;
140 next_send = timer_msec + START_SEND_PRIOD_SLOW;
147 void robot_switches_handler()
149 static uint32_t color_time = 0;
152 if (timer_msec >= color_time + 100)
156 color_time = timer_msec;
158 if (IO0PIN & (1<<COLOR_PIN0))
159 sw |= CAN_SWITCH_COLOR_0;
161 sw &= ~CAN_SWITCH_COLOR_0;
163 if (IO0PIN & (1<<COLOR_PIN1))
164 sw |= CAN_SWITCH_COLOR_1;
166 sw &= ~CAN_SWITCH_COLOR_1;
168 if (IO0PIN & (1<<SWITCH_STRATEGY_PIN))
169 sw &= ~CAN_SWITCH_STRATEGY;
171 sw |= CAN_SWITCH_STRATEGY;
173 if (IO0PIN & (1<<SWITCH_HOME_PIN))
174 sw &= ~CAN_SWITCH_HOME;
176 sw |= CAN_SWITCH_HOME;
178 // COLOR_0 = 1, COLOR_1 = 2, see team color list in robot.h
179 if (!(sw & CAN_SWITCH_COLOR_0) && !(sw & CAN_SWITCH_COLOR_1)){
182 send_rs_str("white\n");}
186 if ((sw & CAN_SWITCH_COLOR_0) && !(sw & CAN_SWITCH_COLOR_1)){
189 send_rs_str("green\n");}
193 if (!(sw & CAN_SWITCH_COLOR_0) && (sw & CAN_SWITCH_COLOR_1)){
196 send_rs_str("yellow\n");}
200 if (sw & CAN_SWITCH_STRATEGY){
203 send_rs_str("strategy\n");
207 if (sw & CAN_SWITCH_HOME){
210 send_rs_str("home\n");
215 // send_rs_int(IO1PIN);
217 // send_rs_str("\n");
219 /* TODO: Put color to the second bit */
221 tx_msg.id = CAN_ROBOT_SWITCHES;
231 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
234 void timer0_irq() __attribute__((interrupt));
235 volatile uint32_t timer_msec = 0, timer_usec = 0;
238 void init_timer0(uint32_t prescale, uint32_t period) {
239 T0TCR = 0x2; /* reset */
242 T0MCR = 0x3; /* match0: reset & irq */
243 T0EMR = 0; /* no ext. match */
244 T0CCR = 0x0; /* no capture */
245 T0TCR = 0x1; /* go! */
250 static unsigned cnt1khz = 0;
252 /* reset timer irq */
255 /* increment timer_usec */
257 /* increment msec @1kHz */
258 if (++cnt1khz == 100) {
263 /* int acknowledge */
268 void CAN_rx(can_msg_t *msg) {
272 memcpy(&rx_msg, msg, sizeof(can_msg_t));//make copy of message
279 //JAW_LEFT_OPEN ff 0xff
280 //JAW_RIGHT_OPEN 0x00
282 //JAW_LEFT_CLOSE 0x80
283 //JAW_RIGHT_CLOSE 0x80
285 //JAW_LEFT_CATCH 0xB8
286 //JAW_RIGHT_CATCH 0x38
288 case CAN_JAW_LEFT_CMD:
291 req = ((rx_msg.data[0]<<8) | (rx_msg.data[1]));
292 spd = rx_msg.data[2];
294 if (req >= 0x50 && req <= 0xD0) {
295 set_servo(JAW_LEFT, (char)req);
298 // if (req >= fsm_jaw_left.min_pos && req <= fsm_jaw_left.max_pos) {
299 // fsm_jaw_left.flags &= ~CAN_JAW_OUT_OF_BOUNDS;
300 // fsm_jaw_left.can_req_position = req;
301 // fsm_jaw_left.can_req_spd = spd;
303 // fsm_jaw_left.flags |= CAN_JAW_OUT_OF_BOUNDS;
306 case CAN_JAW_RIGHT_CMD:
309 req = ((rx_msg.data[0]<<8) | (rx_msg.data[1]));
310 spd = rx_msg.data[2];
312 if (req >= 0x60 && req <= 0xD0) {
313 set_servo(JAW_RIGHT, (char)req);
316 // if (req >= fsm_jaw_right.min_pos && req <= fsm_jaw_right.max_pos) {
317 // fsm_jaw_right.flags &= ~CAN_JAW_OUT_OF_BOUNDS;
318 // fsm_jaw_right.can_req_position = req;
319 // fsm_jaw_right.can_req_spd = spd;
321 // fsm_jaw_right.flags |= CAN_JAW_OUT_OF_BOUNDS;
323 case CAN_CL_SENSOR_CMD:
325 uint32_t option_new = rx_msg.data[0];//option is from range 1-5
339 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
340 void init_periphery(void){
342 can_init_baudrate(CAN_SPEED, CAN_ISR, CAN_rx);//initialization of CAN bus
346 init_timer0(1, CPU_APB_HZ/100000);
347 set_irq_handler(4 /*timer0*/, TIMER_IRQ_PRIORITY, timer0_irq);
352 init_servo(7); //7 is interrupt priority
353 set_servo(JAW_LEFT, 0xB0);
354 set_servo(JAW_RIGHT,0x70);
357 /*********************************************************/
358 void can_send_status(struct fsm *fsm){
360 tx_msg.id = fsm->can_id;
363 tx_msg.data[0] = (fsm->act_pos >> 8) & 0xFF;
364 tx_msg.data[1] = fsm->act_pos & 0xFF;
365 tx_msg.data[2] = (fsm->can_response >> 8) & 0xFF;
366 tx_msg.data[3] = fsm->can_response & 0xFF;
367 tx_msg.data[4] = fsm->flags;
368 /*while*/(can_tx_msg(&tx_msg)); /* CAN erratum workaround */
372 void cl_sensor_send_status(){
374 tx_msg.id = CAN_CL_SENSOR_STATUS;
377 //tx_msg.data[0] = ((IO1PIN & 1<<CL_SENSOR_OUT) != 0) & 0xFF;// 1 - pattern match 0 - no match
378 if((IO1PIN & 1<<CL_SENSOR_OUT) != 0) {
379 tx_msg.data[0] = CAN_CL_SENSOR_PATTERN_MATCH;
380 send_rs_str("trefa\n");
382 (can_tx_msg(&tx_msg));
385 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
386 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
388 void dbg_print_time()
391 unsigned t = timer_usec, i;
392 memset(str, ' ', sizeof(str));
395 for (i=7; t > 0; i--) {
402 void fsm_jaw_init(struct fsm *fsm, enum event event);
406 static uint32_t led_time = 0;
408 if(timer_msec >= led_time + 500)
410 led_time = timer_msec;
413 fsm_vidle.can_req_position = 0x380;
415 fsm_vidle.can_req_position = 0x1e0;
418 deb_led_change(LEDG);
420 send_rs_str("LEFT_JAW: ");
421 send_rs_int(fsm_jaw_left.act_pos);
422 send_rs_str("\tLEFT_FLAGS: ");
423 send_rs_int(fsm_jaw_left.flags);
425 send_rs_str("\tRIGHT_JAW: ");
426 send_rs_int(fsm_jaw_right.act_pos);
427 send_rs_str("\tRIGHT_FLAGS: ");
428 send_rs_int(fsm_jaw_right.flags);
437 static uint32_t bumper_time = 0;
440 if (timer_msec >= bumper_time + 100)
444 bumper_time = timer_msec;
448 /*if (IO1PIN & (1<<BUMPER_REAR_LEFT)){
449 sw &= ~CAN_BUMPER_REAR_LEFT;
451 send_rs_str("rear_left\n");
456 sw |= CAN_BUMPER_REAR_LEFT;
458 // deb_led_off(LEDY);
461 if (IO1PIN & (1<<BUMPER_REAR)){
462 sw &= ~CAN_BUMPER_REAR_RIGHT;
463 sw &= ~CAN_BUMPER_REAR_LEFT;
464 send_rs_str("reart\n");
469 sw |= CAN_BUMPER_REAR_RIGHT;
470 sw |= CAN_BUMPER_REAR_LEFT;
472 // deb_led_off(LEDY);
475 if (IO1PIN & (1<<BUMPER_LEFT)){
477 sw &= ~CAN_BUMPER_LEFT;
479 send_rs_str("left\n");
485 sw |= CAN_BUMPER_LEFT;
487 // deb_led_off(LEDB);
489 if (IO1PIN & (1<<BUMPER_RIGHT)){
490 sw &= ~CAN_BUMPER_RIGHT;
491 send_rs_str("right\n");
495 sw |= CAN_BUMPER_RIGHT;
497 // deb_led_off(LEDG);
499 if (IO1PIN & (1<<BUMPER_LEFT_ACROSS)){
500 sw &= ~CAN_BUMPER_LEFT_ACROSS;
501 send_rs_str("left_across\n");
505 sw |= CAN_BUMPER_LEFT_ACROSS;
507 // deb_led_off(LEDR);
509 if (IO1PIN & (1<<BUMPER_RIGHT_ACROSS)){
510 sw &= ~CAN_BUMPER_RIGHT_ACROSS;
511 send_rs_str("right_across\n");
512 // deb_le0d_on(LEDY);
515 sw |= CAN_BUMPER_RIGHT_ACROSS;
517 // deb_led_off(LEDY);
520 if (sw & (CAN_BUMPER_REAR_LEFT | CAN_BUMPER_REAR_RIGHT | CAN_BUMPER_LEFT | CAN_BUMPER_RIGHT | CAN_BUMPER_LEFT_ACROSS | CAN_BUMPER_RIGHT_ACROSS))
525 // send_rs_int(IO1PIN);
527 // send_rs_str("\n");
528 tx_msg.id = CAN_ROBOT_BUMPERS;
536 void cl_sensor_init(){
537 IO0DIR |= 1<<CL_SENSOR_IN;
538 IO1DIR &= ~(1<<CL_SENSOR_OUT);
539 IO0SET = (1<<CL_SENSOR_IN);
542 cl_sensor_timer = 300 + timer_msec;
543 cl_sensor_refresh = 1700 + timer_msec;
548 volatile unsigned int wait = 5900000;
551 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
552 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
553 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
556 uint32_t main_time = timer_usec;
557 uint32_t status_time_left = timer_usec;
558 uint32_t status_time_right = timer_usec;
559 uint32_t status_time_sensor = timer_msec;
564 SET_PIN(PINSEL0, COLOR_PIN0, PINSEL_0);
565 SET_PIN(PINSEL0, START_PIN, PINSEL_0);
566 SET_PIN(PINSEL1, (SWITCH_STRATEGY_PIN-16), PINSEL_0);
567 SET_PIN(PINSEL1, (COLOR_PIN1-16), PINSEL_0);
568 SET_PIN(PINSEL1, (SWITCH_HOME_PIN - 16), PINSEL_0);
570 PINSEL2 &= ~(1 << 3) ; //setting P1.25:16 as GPIO pins -> GPIO PORT on eb_board
571 IO1DIR &= ~((1<<BUMPER_REAR) | /*(1<<BUMPER_REAR_LEFT) |*/ (1<<BUMPER_RIGHT) | (1<<BUMPER_LEFT) | (1<<BUMPER_RIGHT_ACROSS) | (1<<BUMPER_LEFT_ACROSS));
572 IO0DIR &= ~((1<<COLOR_PIN0) | (1<<COLOR_PIN1)| (1<<SWITCH_HOME_PIN) | (1<<START_PIN) | (1<<SWITCH_STRATEGY_PIN));
577 send_rs_str("Jaws started\n");
578 //uint32_t i = 5000000;
580 // while(i--) for(j = 0; j < 10; j++);
581 //close jaw, max_pos, open jaw min_pos
582 //letf jaw potenciometer on ADC 0, header J32 on board
583 //fsm_jaw_left.max_pos=0x320; //max 0x324
584 //fsm_jaw_left.min_pos=0xB0; //min 0xC3
585 //fsm_jaw_left.act_pos = adc_val[0];
587 //close jaw, max_pos, open jaw min_pos
588 //letf jaw potenciometer on ADC 1, header J33 on board
589 //fsm_jaw_right.max_pos=0x380; //max 0x382
590 //fsm_jaw_right.min_pos=0x010; //min 0xF5
591 //fsm_jaw_right.act_pos = adc_val[1];
593 //left jaw engine is engine A, conector MOTA on board
594 //fsm_jaw_left.engine_en = &engine_A_en;
595 //fsm_jaw_left.engine_dir = &engine_A_dir;
596 //fsm_jaw_left.engine_pwm = &engine_A_pwm;
598 fsm_jaw_left.can_id=CAN_JAW_LEFT_STATUS;
600 //right jaw engine is engine B, conector MOTB on board
601 //fsm_jaw_right.engine_en = &engine_B_en;
602 //fsm_jaw_right.engine_dir = &engine_B_dir;
603 //fsm_jaw_right.engine_pwm = &engine_B_pwm;
605 fsm_jaw_right.can_id=CAN_JAW_RIGHT_STATUS;
608 // init_fsm(&fsm_jaw_right, &fsm_jaw_init);
609 // init_fsm(&fsm_jaw_left, &fsm_jaw_init);
615 if(timer_usec >= main_time + 1000){
616 main_time = timer_usec;
619 //fsm_jaw_left.act_pos = adc_val[0];
620 // run_fsm(&fsm_jaw_left);
622 //fsm_jaw_right.act_pos = adc_val[1];
623 // run_fsm(&fsm_jaw_right);
627 if(timer_msec >= status_time_sensor + 10){
628 status_time_sensor = timer_msec;
629 if(cl_sensor_timer < timer_msec){
630 IO0SET = (1<<CL_SENSOR_IN);
632 if(cl_sensor_refresh < timer_msec){
634 IO0CLR = (1<<CL_SENSOR_IN);
635 cl_sensor_timer = 300*option + timer_msec;
636 cl_sensor_refresh = 2000 - 300*option + timer_msec;
642 cl_sensor_send_status();
643 // feedback = (IO0PIN & 1<<CL_SENSOR_OUT) != 0;
644 // if(feedback) send_rs_str("shoda barev\n");
645 // else send_rs_str("jina barva\n");
647 //CAN send left jaw status
648 if (timer_msec >= status_time_left + 100 /*|| //repeat sending message every 100 ms
649 fsm_jaw_left.trigger_can_send*/) { //or when something important happen
650 //fsm_jaw_left.trigger_can_send = false;
651 status_time_left = timer_msec; //save new time, when message was sent
652 can_send_status(&fsm_jaw_left);
655 // CAN send left jaw status
656 if (timer_msec >= status_time_right + 100 /*|| //repeat sending message every 100 ms
657 fsm_jaw_right.trigger_can_send*/) { //or when something important happen
658 //fsm_jaw_right.trigger_can_send = false;
659 status_time_right = timer_msec; //save new time, when message was sent
660 can_send_status(&fsm_jaw_right);
667 robot_switches_handler();