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>
36 #include <expansion.h>
38 #define CAN_SPEED 1000000 //< CAN bus speed
43 #define TIMER_IRQ_PRIORITY 5
48 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
52 #define END_SWITCH_UP_PIN EXPPORT_4 //pin 4, exp. port on board
53 #define END_SWITCH_DOWN_PIN EXPPORT_3 //pin 3, exp. port on board
54 #define SWITCH_HOME_PIN EXPPORT_6 //pin 6, exp. port on board
55 #define START_PIN EXPPORT_7 //pin 7, exp. port on board
56 #define COLOR_PIN EXPPORT_5 //pin 5, exp. port on board
57 #define SWITCH_STRATEGY_PIN EXPPORT_8 //pin 8, exp. port on board
59 #define START_SEND_PRIOD_FAST 50 /* [miliseconds] */
60 #define START_SEND_PRIOD_SLOW 300 /* [miliseconds] */
61 #define START_SEND_FAST_COUNT 10 /* How many times to send start with small period (after a change) */
63 #define LIFT_IRC_VAL_MAX 0x19C
64 #define LIFT_IRC_VAL_MIN 0x0
66 #define IRC_A_PIN 2 //pin 1, exp. port on board
67 #define IRC_B_PIN 3 //pin 2, exp. port on board
69 #define IRC_A_MASK 0x04 //(1<<IRC_A)
70 #define IRC_B_MASK 0x08 //(1<<IRC_B)
71 #define IRC_AB_MASK 0x0C //((1<<IRC_A)&(1<<IRC_B))
73 void lift_switches_handler(void);
75 void lift_switches_handler()
77 if (IO0PIN & (1<<END_SWITCH_UP_PIN)){
78 fsm_lift.flags &= ~CAN_LIFT_SWITCH_UP;
81 fsm_lift.flags |= CAN_LIFT_SWITCH_UP;
85 if (IO0PIN & (1<<END_SWITCH_DOWN_PIN)){
86 fsm_lift.flags &= ~CAN_LIFT_SWITCH_DOWN;
89 fsm_lift.flags |= CAN_LIFT_SWITCH_DOWN;
93 if (IO0PIN & (1<<SWITCH_HOME_PIN)){
94 fsm_lift.flags &= ~CAN_LIFT_SWITCH_HOME;
97 fsm_lift.flags |= CAN_LIFT_SWITCH_HOME;
100 // if (IO0PIN & (1<<IRC_A_PIN)){
101 // deb_led_off(LEDR);
105 // if (IO0PIN & (1<<IRC_B_PIN)){
106 // deb_led_off(LEDR);
112 //source code from http://www.vosrk.cz/robotika/Stavba/Enkoder.pdf
113 int32_t irc_read_tick(){
115 static uint16_t cnt_up = 0;
116 static uint16_t cnt_down = 0;
117 static uint16_t last_irc = 0;
118 static int32_t position = 0;
121 irc = IO0PIN & IRC_AB_MASK;
122 if ((irc & IRC_B_MASK) != 0){
126 temp = (irc - last_irc) & IRC_AB_MASK;
130 if (temp == IRC_A_MASK){
131 /* count 100times slower - we do not need 250 ticks per milimeter*/
132 if (++cnt_down >= 100) {
135 deb_led_change(LEDB);
138 } else if (temp == IRC_AB_MASK){
139 /* count 100times slower - we do not need 250 ticks per milimeter*/
140 if (++cnt_up >= 100) {
143 deb_led_change(LEDB);
150 void init_motors(void){
152 init_engine_A(); // initialization of PWM unit
153 engine_A_en(ENGINE_EN_ON); //enable motor A
154 engine_A_dir(ENGINE_DIR_FW); //set direction
155 engine_A_pwm(0); // STOP pwm is in percent, range 0~100~200
159 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
160 void set_irq_handler(uint8_t source, uint8_t irq_vect, void (*handler)()) {
161 /* set interrupt vector */
162 ((uint32_t*)&VICVectAddr0)[irq_vect] = (uint32_t)handler;
163 ((uint32_t*)&VICVectCntl0)[irq_vect] = 0x20 | source;
164 /* enable interrupt */
165 VICIntEnable = 1<<source;
168 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
171 void timer0_irq() __attribute__((interrupt));
172 volatile uint32_t timer_msec = 0, timer_usec = 0;
174 void init_timer0(uint32_t prescale, uint32_t period) {
175 T0TCR = 0x2; /* reset */
178 T0MCR = 0x3; /* match0: reset & irq */
179 T0EMR = 0; /* no ext. match */
180 T0CCR = 0x0; /* no capture */
181 T0TCR = 0x1; /* go! */
185 static unsigned cnt1khz = 0;
187 /* reset timer irq */
190 /* increment timer_usec */
192 /* increment msec @1kHz */
193 if (++cnt1khz == 100) {
198 /* int acknowledge */
203 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
204 void start_button(void)
207 bool start_condition;
208 static bool last_start_condition = 0;
210 static int count = 0;
211 static uint32_t next_send = 0;
214 start_condition = (IO0PIN & (1<<START_PIN)) == 0;
216 if (start_condition != last_start_condition) {
219 last_start_condition = start_condition;
221 next_send = timer_msec; /* Send now */
223 fsm_lift.flags |= CAN_LIFT_START;
226 if (timer_msec >= next_send) {
227 msg.id = CAN_ROBOT_CMD;
230 msg.data[0] = start_condition;
232 // send_rs_str("start\n");
234 /*while*/ (can_tx_msg(&msg));
236 if (count < START_SEND_FAST_COUNT) {
238 next_send = timer_msec + START_SEND_PRIOD_FAST;
240 next_send = timer_msec + START_SEND_PRIOD_SLOW;
247 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
248 void CAN_rx(can_msg_t *msg) {
252 memcpy(&rx_msg, msg, sizeof(can_msg_t));//make copy of message
261 req = ((rx_msg.data[0]<<8) | (rx_msg.data[1]));
262 spd = rx_msg.data[2];
263 fsm_lift.can_req_homing=rx_msg.data[3];
265 if (req >= LIFT_IRC_VAL_MIN && req <= LIFT_IRC_VAL_MAX) {
266 fsm_lift.flags &= ~CAN_LIFT_OUT_OF_BOUNDS;
267 fsm_lift.can_req_position = req;// save new req position of lift
268 fsm_lift.can_req_spd = spd;// save new req spd of lift
270 fsm_lift.flags |= CAN_LIFT_OUT_OF_BOUNDS;
279 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
280 void init_periphery(void){
282 can_init_baudrate(CAN_SPEED, CAN_ISR, CAN_rx);//initialization of CAN bus
286 init_timer0(1, CPU_APB_HZ/100000);
287 set_irq_handler(4 /*timer0*/, TIMER_IRQ_PRIORITY, timer0_irq);
290 // init_adc(ADC_ISR);
292 /*********************************************************/
293 void can_send_status(void)
296 tx_msg.id = CAN_LIFT_STATUS;
299 tx_msg.data[0] = (fsm_lift.act_pos >> 8) & 0xFF;
300 tx_msg.data[1] = fsm_lift.act_pos & 0xFF;
301 tx_msg.data[2] = (fsm_lift.can_response >> 8) & 0xFF;
302 tx_msg.data[3] = fsm_lift.can_response & 0xFF;
303 tx_msg.data[4] = fsm_lift.flags;
304 /*while*/(can_tx_msg(&tx_msg)); /* CAN erratum workaround */
307 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
308 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
310 void dbg_print_time()
313 unsigned t = timer_usec, i;
314 memset(str, ' ', sizeof(str));
317 for (i=7; t > 0; i--) {
324 void fsm_lift_init(struct fsm *fsm, enum event event);
329 static uint32_t led_time = 0;
331 if(timer_msec >= led_time + 500)
333 led_time = timer_msec;
336 // fsm_lift.can_req_position = 0x380;
338 // fsm_lift.can_req_position = 0x1e0;
341 deb_led_change(LEDG);
343 send_rs_str("ACT_POS\t");
344 send_rs_int(fsm_lift.act_pos);
346 send_rs_str("CAN_FLAGS\t");
347 send_rs_int(fsm_lift.flags);
352 void robot_switches_handler()
354 static uint32_t color_time = 0;
357 if (timer_msec >= color_time + 100)
361 color_time = timer_msec;
363 if (IO0PIN & (1<<COLOR_PIN))
364 sw |= CAN_SWITCH_COLOR;
366 sw &= ~CAN_SWITCH_COLOR;
368 if (IO0PIN & (1<<SWITCH_STRATEGY_PIN))
369 sw &= ~CAN_SWITCH_STRATEGY;
371 sw |= CAN_SWITCH_STRATEGY;
373 if (sw & CAN_SWITCH_COLOR){
376 send_rs_str("color\n");}
380 if (sw & CAN_SWITCH_STRATEGY){
383 send_rs_str("strategy\n");
388 // send_rs_int(IO1PIN);
390 // send_rs_str("\n");
392 /* TODO: Put color to the second bit */
394 tx_msg.id = CAN_ROBOT_SWITCHES;
403 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
404 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
405 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
408 uint32_t main_time = timer_usec;
409 uint32_t status_time = timer_usec;
411 //lift motor is motor A, MOTA connctor on board
414 SET_PIN(PINSEL0, IRC_A_PIN, PINSEL_0);
415 SET_PIN(PINSEL0, IRC_B_PIN, PINSEL_0);
417 SET_PIN(PINSEL0, END_SWITCH_UP_PIN, PINSEL_0);
418 SET_PIN(PINSEL0, END_SWITCH_DOWN_PIN, PINSEL_0);
420 SET_PIN(PINSEL0, START_PIN, PINSEL_0); //init of start pin
421 SET_PIN(PINSEL1, (COLOR_PIN - 16), PINSEL_0); //init of color pin
422 SET_PIN(PINSEL1, (SWITCH_STRATEGY_PIN - 16), PINSEL_0); //init of strategy pin
423 SET_PIN(PINSEL1, (SWITCH_HOME_PIN - 16), PINSEL_0); //init of home pin
425 IO0DIR &= ~((1<<START_PIN) | (1<<SWITCH_HOME_PIN) | (1 << COLOR_PIN) | (1 << SWITCH_STRATEGY_PIN));
426 IO0DIR &= ~((1<<END_SWITCH_UP_PIN) | (1<<END_SWITCH_DOWN_PIN));
427 IO0DIR &= ~((1<<IRC_A_PIN) | (1<<IRC_B_PIN));
428 send_rs_str("Lift started\n");
430 fsm_lift.act_pos = 0;
431 init_fsm(&fsm_lift, &fsm_lift_init);
436 if(timer_usec >= main_time + 1000)
438 main_time = timer_usec;
442 // fsm_lift.act_pos = adc_val[0];
447 if (timer_msec >= status_time + 100 || //repeat sending message every 100 ms
448 fsm_lift.trigger_can_send) { //or when something important happen
449 fsm_lift.trigger_can_send = false;
450 status_time = timer_msec; //save new time, when message was sent
454 fsm_lift.act_pos = irc_read_tick();
457 robot_switches_handler();
458 lift_switches_handler();