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
48 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
51 #define IRC_A 2 //pin 1, exp. port on board
52 #define IRC_B 3 //pin 2, exp. port on board
54 #define IRC_A_MASK (1<<IRC_A)
55 #define IRC_B_MASK (1<<IRC_B)
56 #define IRC_AB_MASK ((1<<IRC_A)&(1<<IRC_B))
58 int irc_read_tick(int last_irc);
62 SET_PIN(PINSEL0, IRC_A, PINSEL_0);
63 SET_PIN(PINSEL0, IRC_B, PINSEL_0);
65 SET_PIN(PINSEL0, END_SWITCH_UP, PINSEL_0);
66 SET_PIN(PINSEL0, END_SWITCH_DOWN, PINSEL_0);
71 int irc_read_tick(int last_irc){
75 irc = IO0PIN & IRC_AB_MASK;
76 if ((irc & IRC_B_MASK) != 0)
79 temp = (irc - last_irc) & IRC_AB_MASK;
81 if (temp == IRC_A_MASK){ // nebo zaporny (-1)
84 else if (temp == IRC_AB_MASK){
90 void init_motors(void){
92 init_engine_A(); // initialization of PWM unit
93 engine_A_en(ENGINE_EN_ON); //enable motor A
94 engine_A_dir(ENGINE_DIR_FW); //set direction
95 engine_A_pwm(0); // STOP pwm is in percent, range 0~100~200
99 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
100 void set_irq_handler(uint8_t source, uint8_t irq_vect, void (*handler)()) {
101 /* set interrupt vector */
102 ((uint32_t*)&VICVectAddr0)[irq_vect] = (uint32_t)handler;
103 ((uint32_t*)&VICVectCntl0)[irq_vect] = 0x20 | source;
104 /* enable interrupt */
105 VICIntEnable = 1<<source;
108 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
111 void timer0_irq() __attribute__((interrupt));
112 volatile uint32_t timer_msec = 0, timer_usec = 0;
114 void init_timer0(uint32_t prescale, uint32_t period) {
115 T0TCR = 0x2; /* reset */
118 T0MCR = 0x3; /* match0: reset & irq */
119 T0EMR = 0; /* no ext. match */
120 T0CCR = 0x0; /* no capture */
121 T0TCR = 0x1; /* go! */
125 static unsigned cnt1khz = 0;
127 /* reset timer irq */
130 fsm_lift.act_pos=fsm_lift.act_pos+irc_read_tick(last_irc);
132 /* increment timer_usec */
134 /* increment msec @1kHz */
135 if (++cnt1khz == 100) {
140 /* int acknowledge */
145 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
147 #define START_PIN 15 // start pin
148 #define START_SEND_PRIOD_FAST 50 /* [miliseconds] */
149 #define START_SEND_PRIOD_SLOW 300 /* [miliseconds] */
150 #define START_SEND_FAST_COUNT 10 /* How many times to send start with small period (after a change) */
153 void start_button(void)
156 bool start_condition;
157 static bool last_start_condition = 0;
159 static int count = 0;
160 static uint32_t next_send = 0;
163 start_condition = (IO0PIN & (1<<START_PIN)) == 0;
165 if (start_condition != last_start_condition) {
168 last_start_condition = start_condition;
170 next_send = timer_msec; /* Send now */
173 if (timer_msec >= next_send) {
174 msg.id = CAN_ROBOT_CMD;
177 msg.data[0] = start_condition;
179 // send_rs_str("start\n");
181 /*while*/ (can_tx_msg(&msg));
183 if (count < START_SEND_FAST_COUNT) {
185 next_send = timer_msec + START_SEND_PRIOD_FAST;
187 next_send = timer_msec + START_SEND_PRIOD_SLOW;
194 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
195 void CAN_rx(can_msg_t *msg) {
199 memcpy(&rx_msg, msg, sizeof(can_msg_t));//make copy of message
208 req = ((rx_msg.data[0]<<8) | (rx_msg.data[1]));
209 spd = rx_msg.data[2];
210 //TODO doplnit omezujici hodnoty
211 if (req >= 0x150 && req <= 0x3e0) {
212 fsm_lift.flags &= ~CAN_LIFT_OUT_OF_BOUNDS;
213 fsm_lift.can_req_position = req;// save new req position of lift
214 fsm_lift.can_req_spd = spd;// save new req spd of lift
216 fsm_lift.flags |= CAN_LIFT_OUT_OF_BOUNDS;
225 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
226 void init_periphery(void){
228 can_init_baudrate(CAN_SPEED, CAN_ISR, CAN_rx);//initialization of CAN bus
232 init_timer0(1, CPU_APB_HZ/100000);
233 set_irq_handler(4 /*timer0*/, TIMER_IRQ_PRIORITY, timer0_irq);
236 // init_adc(ADC_ISR);
241 /*********************************************************/
242 void can_send_status(void)
245 tx_msg.id = CAN_LIFT_STATUS;
248 tx_msg.data[0] = (fsm_lift.act_pos >> 8) & 0xFF;
249 tx_msg.data[1] = fsm_lift.act_pos & 0xFF;
250 tx_msg.data[2] = (fsm_lift.can_response >> 8) & 0xFF;
251 tx_msg.data[3] = fsm_lift.can_response & 0xFF;
252 tx_msg.data[4] = fsm_lift.flags;
253 /*while*/(can_tx_msg(&tx_msg)); /* CAN erratum workaround */
256 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
257 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
259 void dbg_print_time()
262 unsigned t = timer_usec, i;
263 memset(str, ' ', sizeof(str));
266 for (i=7; t > 0; i--) {
273 void fsm_lift_init(struct fsm *fsm, enum event event);
278 static uint32_t led_time = 0;
280 if(timer_msec >= led_time + 500)
282 led_time = timer_msec;
285 // fsm_lift.can_req_position = 0x380;
287 // fsm_lift.can_req_position = 0x1e0;
290 deb_led_change(LEDG);
291 send_rs_int(fsm_lift.act_pos);
298 #define COLOR_PIN 18 //pin 5, exp. port on board
302 static uint32_t color_time = 0;
305 if (timer_msec >= color_time + 100)
309 color_time = timer_msec;
311 if (IO0PIN & (1<<COLOR_PIN))
312 sw |= CAN_SWITCH_COLOR;
314 sw &= ~CAN_SWITCH_COLOR;
317 if (sw & CAN_SWITCH_COLOR){
320 send_rs_str("barva\n");}
324 // send_rs_int(IO1PIN);
326 // send_rs_str("\n");
328 /* TODO: Put color to the second bit */
330 tx_msg.id = CAN_ROBOT_SWITCHES;
339 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
340 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
341 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
344 uint32_t main_time = timer_usec;
345 uint32_t status_time = timer_usec;
347 //lift motor is motor A, MOTA connctor on board
350 SET_PIN(PINSEL0, START_PIN, PINSEL_0); // inicializace start pinu
351 SET_PIN(PINSEL0, 3, PINSEL_0); //init of color pin
353 send_rs_str("Lift started\n");
355 fsm_lift.act_pos = 0;
356 init_fsm(&fsm_lift, &fsm_lift_init);
361 if(timer_usec >= main_time + 1000)
363 main_time = timer_usec;
367 // fsm_lift.act_pos = adc_val[0];
372 if (timer_msec >= status_time + 100 || //repeat sending message every 100 ms
373 fsm_lift.trigger_can_send) { //or when something important happen
374 fsm_lift.trigger_can_send = false;
375 status_time = timer_msec; //save new time, when message was sent