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 #define CAN_SPEED 1000000 //< CAN bus speed
42 #define TIMER_IRQ_PRIORITY 5
47 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
51 #define END_SWITCH_UP 9 //pin 4, exp. port on board
52 #define END_SWITCH_DOWN 8 //pin 3, exp. port on board
53 #define SWITCH_HOME 19 //pin 6, exp. port on board
55 void lift_switches_handler(void);
57 void lift_switches_handler()
59 if (IO0PIN & (1<<END_SWITCH_UP)){
60 fsm_lift.flags |= CAN_LIFT_SWITCH_UP;
64 fsm_lift.flags &= ~CAN_LIFT_SWITCH_UP;
68 if (IO0PIN & (1<<END_SWITCH_DOWN)){
69 fsm_lift.flags |= CAN_LIFT_SWITCH_DOWN;
73 fsm_lift.flags &= ~CAN_LIFT_SWITCH_DOWN;
77 if (IO0PIN & (1<<SWITCH_HOME)){
78 fsm_lift.flags |= CAN_LIFT_SWITCH_HOME;
82 fsm_lift.flags &= ~CAN_LIFT_SWITCH_HOME;
87 #define LIFT_IRC_VAL_MAX 0xA9B0
88 #define LIFT_IRC_VAL_MIN 0x0
90 #define IRC_A 2 //pin 1, exp. port on board
91 #define IRC_B 3 //pin 2, exp. port on board
93 #define IRC_A_MASK 0x04 //(1<<IRC_A)
94 #define IRC_B_MASK 0x08 //(1<<IRC_B)
95 #define IRC_AB_MASK 0x0C //((1<<IRC_A)&(1<<IRC_B))
97 int irc_read_tick(uint16_t* last_irc);
101 SET_PIN(PINSEL0, IRC_A, PINSEL_0);
102 SET_PIN(PINSEL0, IRC_B, PINSEL_0);
104 SET_PIN(PINSEL0, END_SWITCH_UP, PINSEL_0);
105 SET_PIN(PINSEL0, END_SWITCH_DOWN, PINSEL_0);
109 //source code from http://www.vosrk.cz/robotika/Stavba/Enkoder.pdf
110 int irc_read_tick(uint16_t* last_irc){
114 irc = IO0PIN & IRC_AB_MASK;
115 if ((irc & IRC_B_MASK) != 0){
119 // send_rs_str("IRC\t");
121 // send_rs_str("\n");
123 // send_rs_str("LAST_IRC\t");
124 // send_rs_int(*last_irc);
125 // send_rs_str("\n");
127 temp = (irc - *last_irc) & IRC_AB_MASK;
131 // send_rs_str("TEMP\t");
132 // send_rs_int(temp);
133 // send_rs_str("\n");
135 if (temp == IRC_A_MASK){ // nebo zaporny (-1)
138 else if (temp == IRC_AB_MASK){
144 void init_motors(void){
146 init_engine_A(); // initialization of PWM unit
147 engine_A_en(ENGINE_EN_ON); //enable motor A
148 engine_A_dir(ENGINE_DIR_FW); //set direction
149 engine_A_pwm(0); // STOP pwm is in percent, range 0~100~200
153 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
154 void set_irq_handler(uint8_t source, uint8_t irq_vect, void (*handler)()) {
155 /* set interrupt vector */
156 ((uint32_t*)&VICVectAddr0)[irq_vect] = (uint32_t)handler;
157 ((uint32_t*)&VICVectCntl0)[irq_vect] = 0x20 | source;
158 /* enable interrupt */
159 VICIntEnable = 1<<source;
162 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
165 void timer0_irq() __attribute__((interrupt));
166 volatile uint32_t timer_msec = 0, timer_usec = 0;
168 void init_timer0(uint32_t prescale, uint32_t period) {
169 T0TCR = 0x2; /* reset */
172 T0MCR = 0x3; /* match0: reset & irq */
173 T0EMR = 0; /* no ext. match */
174 T0CCR = 0x0; /* no capture */
175 T0TCR = 0x1; /* go! */
179 static unsigned cnt1khz = 0;
181 /* reset timer irq */
184 /* increment timer_usec */
186 /* increment msec @1kHz */
187 if (++cnt1khz == 100) {
192 /* int acknowledge */
197 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
199 #define START_PIN 15 //pin 7, exp. port on board
200 #define START_SEND_PRIOD_FAST 50 /* [miliseconds] */
201 #define START_SEND_PRIOD_SLOW 300 /* [miliseconds] */
202 #define START_SEND_FAST_COUNT 10 /* How many times to send start with small period (after a change) */
205 void start_button(void)
208 bool start_condition;
209 static bool last_start_condition = 0;
211 static int count = 0;
212 static uint32_t next_send = 0;
215 start_condition = (IO0PIN & (1<<START_PIN)) == 0;
217 if (start_condition != last_start_condition) {
220 last_start_condition = start_condition;
222 next_send = timer_msec; /* Send now */
224 fsm_lift.flags |= CAN_LIFT_START;
227 if (timer_msec >= next_send) {
228 msg.id = CAN_ROBOT_CMD;
231 msg.data[0] = start_condition;
233 // send_rs_str("start\n");
235 /*while*/ (can_tx_msg(&msg));
237 if (count < START_SEND_FAST_COUNT) {
239 next_send = timer_msec + START_SEND_PRIOD_FAST;
241 next_send = timer_msec + START_SEND_PRIOD_SLOW;
248 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
249 void CAN_rx(can_msg_t *msg) {
253 memcpy(&rx_msg, msg, sizeof(can_msg_t));//make copy of message
262 req = ((rx_msg.data[0]<<8) | (rx_msg.data[1]));
263 spd = rx_msg.data[2];
264 fsm_lift.can_req_homing=rx_msg.data[3];
266 if (req >= LIFT_IRC_VAL_MIN && req <= LIFT_IRC_VAL_MAX) {
267 fsm_lift.flags &= ~CAN_LIFT_OUT_OF_BOUNDS;
268 fsm_lift.can_req_position = req;// save new req position of lift
269 fsm_lift.can_req_spd = spd;// save new req spd of lift
271 fsm_lift.flags |= CAN_LIFT_OUT_OF_BOUNDS;
280 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
281 void init_periphery(void){
283 can_init_baudrate(CAN_SPEED, CAN_ISR, CAN_rx);//initialization of CAN bus
287 init_timer0(1, CPU_APB_HZ/100000);
288 set_irq_handler(4 /*timer0*/, TIMER_IRQ_PRIORITY, timer0_irq);
291 // init_adc(ADC_ISR);
296 /*********************************************************/
297 void can_send_status(void)
300 tx_msg.id = CAN_LIFT_STATUS;
303 tx_msg.data[0] = (fsm_lift.act_pos >> 8) & 0xFF;
304 tx_msg.data[1] = fsm_lift.act_pos & 0xFF;
305 tx_msg.data[2] = (fsm_lift.can_response >> 8) & 0xFF;
306 tx_msg.data[3] = fsm_lift.can_response & 0xFF;
307 tx_msg.data[4] = fsm_lift.flags;
308 /*while*/(can_tx_msg(&tx_msg)); /* CAN erratum workaround */
311 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
312 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
314 void dbg_print_time()
317 unsigned t = timer_usec, i;
318 memset(str, ' ', sizeof(str));
321 for (i=7; t > 0; i--) {
328 void fsm_lift_init(struct fsm *fsm, enum event event);
333 static uint32_t led_time = 0;
335 if(timer_msec >= led_time + 500)
337 led_time = timer_msec;
340 // fsm_lift.can_req_position = 0x380;
342 // fsm_lift.can_req_position = 0x1e0;
345 deb_led_change(LEDG);
347 send_rs_str("ACT_POS\t");
348 send_rs_int(fsm_lift.act_pos);
350 send_rs_str("CAN_FLAGS\t");
351 send_rs_int(fsm_lift.flags);
358 #define COLOR_PIN 18 //pin 5, exp. port on board
362 static uint32_t color_time = 0;
365 if (timer_msec >= color_time + 100)
369 color_time = timer_msec;
371 if (IO0PIN & (1<<COLOR_PIN))
372 sw |= CAN_SWITCH_COLOR;
374 sw &= ~CAN_SWITCH_COLOR;
377 if (sw & CAN_SWITCH_COLOR){
380 send_rs_str("barva\n");}
384 // send_rs_int(IO1PIN);
386 // send_rs_str("\n");
388 /* TODO: Put color to the second bit */
390 tx_msg.id = CAN_ROBOT_SWITCHES;
399 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
400 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
401 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
404 uint32_t main_time = timer_usec;
405 uint32_t status_time = timer_usec;
407 static uint16_t last_irc=0;
409 //lift motor is motor A, MOTA connctor on board
412 SET_PIN(PINSEL0, START_PIN, PINSEL_0); //init of start pin
413 SET_PIN(PINSEL0, 3, PINSEL_0); //init of color pin
414 SET_PIN(PINSEL0, 4, PINSEL_0); //init of home pin
416 send_rs_str("Lift started\n");
418 fsm_lift.act_pos = 0;
419 init_fsm(&fsm_lift, &fsm_lift_init);
424 if(timer_usec >= main_time + 1000)
426 main_time = timer_usec;
430 // fsm_lift.act_pos = adc_val[0];
435 if (timer_msec >= status_time + 100 || //repeat sending message every 100 ms
436 fsm_lift.trigger_can_send) { //or when something important happen
437 fsm_lift.trigger_can_send = false;
438 status_time = timer_msec; //save new time, when message was sent
443 fsm_lift.act_pos=fsm_lift.act_pos+irc_read_tick(&last_irc);
448 lift_switches_handler();