5 * @brief Display-ORTE bridge
7 * Copyright: (c) 2010 CTU Dragons
8 * CTU FEE - Department of Control Engineering
15 #include <roboorte_robottype.h>
16 //#include <pthread.h>
26 struct sercom_data* sercom;
29 static void sig_handler(int sig)
36 * Subtract the `struct timespec' values X and Y,
37 * storing the result in RESULT (result = x - y).
38 * Return 1 if the difference is negative, otherwise 0.
40 int timespec_subtract (struct timespec *result,
44 /* Perform the carry for the later subtraction by updating Y. */
45 if (x->tv_nsec < y->tv_nsec) {
46 int num_sec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
47 y->tv_nsec -= 1000000000 * num_sec;
50 if (x->tv_nsec - y->tv_nsec > 1000000000) {
51 int num_sec = (x->tv_nsec - y->tv_nsec) / 1000000000;
52 y->tv_nsec += 1000000000 * num_sec;
56 /* Compute the time remaining to wait.
57 `tv_nsec' is certainly positive. */
58 result->tv_sec = x->tv_sec - y->tv_sec;
59 result->tv_nsec = x->tv_nsec - y->tv_nsec;
61 /* Return 1 if result is negative. */
62 return x->tv_sec < y->tv_sec;
65 bool miliseconds_elapsed_since(struct timespec *t, unsigned miliseconds)
67 struct timespec now, diff;
68 unsigned long long elapsed;
70 if (t->tv_sec == 0 && t->tv_nsec == 0)
71 return true; /* Always elapsed after program start */
73 clock_gettime(CLOCK_MONOTONIC, &now);
74 timespec_subtract(&diff, &now, t);
75 elapsed = diff.tv_sec * 1000 + diff.tv_nsec/1000000;
76 return elapsed > miliseconds;
81 void rcv_pwr_voltage_cb (const ORTERecvInfo *info, void *vinstance,
82 void *recvCallBackParam)
84 UDE_hw_status_t status = STATUS_FAILED;
85 static UDE_hw_status_t last_status;
86 static struct timespec last_sent;
87 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
88 switch (info->status) {
90 uoled_display_voltage(orte_data->pwr_voltage.voltage33,orte_data->pwr_voltage.voltage50,
91 orte_data->pwr_voltage.voltage80, orte_data->pwr_voltage.voltageBAT);
95 status = STATUS_FAILED;
98 if (status != last_status ||
99 miliseconds_elapsed_since(&last_sent, 1000)) {
100 uoled_display_status(PWR, status);
101 clock_gettime(CLOCK_MONOTONIC, &last_sent);
103 last_status = status;
106 void rcv_odo_data_cb(const ORTERecvInfo *info, void *vinstance,
107 void *recvCallBackParam)
109 UDE_hw_status_t status = STATUS_FAILED;
110 static UDE_hw_status_t last_status;
111 static struct timespec last_sent;
112 //struct odo_data_type *instance = (struct odo_data_type *)vinstance;
113 switch (info->status) {
118 status = STATUS_FAILED;
121 /* Neni potreba aktualizovat stav na displeji 25x za sekundu */
122 if (status != last_status ||
123 miliseconds_elapsed_since(&last_sent, 1000)) {
124 uoled_display_status(ODO, status);
125 clock_gettime(CLOCK_MONOTONIC, &last_sent);
127 last_status = status;
130 void rcv_robot_cmd_cb(const ORTERecvInfo *info, void *vinstance,
131 void *recvCallBackParam)
133 UDE_hw_status_t status = STATUS_FAILED;
134 static UDE_hw_status_t last_status;
135 static struct timespec last_sent;
136 struct robot_cmd_type *instance = (struct robot_cmd_type *)vinstance;
138 switch (info->status) {
140 if (instance->start_condition)
141 status = STATUS_WARNING; /* Start plug must be plugged before competition start */
146 status = STATUS_FAILED;
149 if (status != last_status ||
150 miliseconds_elapsed_since(&last_sent, 500)) {
151 uoled_display_status(STA, status);
152 clock_gettime(CLOCK_MONOTONIC, &last_sent);
154 last_status = status;
157 void rcv_robot_swicthes_cb(const ORTERecvInfo *info, void *vinstance,
158 void *recvCallBackParam)
160 UDE_hw_status_t status = STATUS_FAILED;
161 static char last_color;
162 static struct timespec last_sent;
163 struct robot_switches_type *instance = (struct robot_switches_type *)vinstance;
165 switch (info->status) {
167 if (instance->team_color != last_color ||
168 miliseconds_elapsed_since(&last_sent, 1000)) {
169 uoled_display_color(instance->team_color);
170 clock_gettime(CLOCK_MONOTONIC, &last_sent);
172 last_color = instance->team_color;
174 status = STATUS_FAILED;
179 void rcv_motion_status_cb(const ORTERecvInfo *info, void *vinstance,
180 void *recvCallBackParam)
182 struct motion_status_type *m = (struct motion_status_type *)vinstance;
183 UDE_hw_status_t status = STATUS_FAILED;
184 static UDE_hw_status_t last_status;
185 static struct timespec last_sent;
186 switch (info->status) {
188 if (m->err_left == 0 && m->err_right == 0)
191 status = STATUS_WARNING;
194 status = STATUS_FAILED;
197 /* Neni potreba aktualizovat stav na displeji 25x za sekundu */
198 if (status != last_status ||
199 miliseconds_elapsed_since(&last_sent, 1000)) {
200 uoled_display_status(MOT, status);
201 clock_gettime(CLOCK_MONOTONIC, &last_sent);
203 last_status = status;
206 void rcv_vidle_status_cb(const ORTERecvInfo *info, void *vinstance,
207 void *recvCallBackParam)
209 struct vidle_status_type *m = (struct vidle_status_type *)vinstance;
210 UDE_hw_status_t status = STATUS_FAILED;
211 static UDE_hw_status_t last_status;
212 static struct timespec last_sent;
213 switch (info->status) {
218 status = STATUS_WARNING;
221 status = STATUS_FAILED;
224 /* Neni potreba aktualizovat stav na displeji 25x za sekundu */
225 if (status != last_status ||
226 miliseconds_elapsed_since(&last_sent, 1000)) {
227 uoled_display_status(VID, status);
228 clock_gettime(CLOCK_MONOTONIC, &last_sent);
230 last_status = status;
233 void rcv_camera_result_cb(const ORTERecvInfo *info, void *vinstance,
234 void *recvCallBackParam)
236 UDE_hw_status_t status = STATUS_FAILED;
237 static UDE_hw_status_t last_status;
238 static struct timespec last_sent;
239 struct camera_result_type *instance = (struct camera_result_type *)vinstance;
240 switch (info->status) {
242 if (instance->error == 0)
245 status = STATUS_WARNING;
248 status = STATUS_FAILED;
251 if (status != last_status ||
252 miliseconds_elapsed_since(&last_sent, 1000)) {
253 uoled_display_status(CAM, status);
254 clock_gettime(CLOCK_MONOTONIC, &last_sent);
256 last_status = status;
257 /* TODO: Show recognized corns */
260 void rcv_hokuyo_scan_cb(const ORTERecvInfo *info, void *vinstance,
261 void *recvCallBackParam)
263 UDE_hw_status_t status = STATUS_FAILED;
264 static UDE_hw_status_t last_status;
265 static struct timespec last_sent;
266 //struct hokuyo_scan_type *instance = (struct hokuyo_scan_type *)vinstance;
267 switch (info->status) {
272 status = STATUS_FAILED;
275 if (status != last_status ||
276 miliseconds_elapsed_since(&last_sent, 1000)) {
277 uoled_display_status(HOK, status);
278 clock_gettime(CLOCK_MONOTONIC, &last_sent);
280 last_status = status;
283 void rcv_est_pos_best_cb (const ORTERecvInfo *info, void *vinstance,
284 void *recvCallBackParam)
286 UDE_hw_status_t status = STATUS_FAILED;
287 static UDE_hw_status_t last_status;
288 static struct timespec last_sent;
289 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
290 switch (info->status) {
295 status = STATUS_FAILED;
298 if (status != last_status ||
299 miliseconds_elapsed_since(&last_sent, 100)) {
300 uoled_display_status(APP, status);
301 if (status == STATUS_OK)
302 uoled_display_position(orte_data->est_pos_best.x, orte_data->est_pos_best.y, orte_data->est_pos_best.phi);
303 clock_gettime(CLOCK_MONOTONIC, &last_sent);
305 last_status = status;
308 void rcv_fsm_main_cb(const ORTERecvInfo *info, void *vinstance,
309 void *recvCallBackParam)
311 char status[MGS_LENGTH_DISPLAY_SM];
312 static char last_status[MGS_LENGTH_DISPLAY_SM];
313 static struct timespec last_sent;
314 struct fsm_state_type *fsm_state = (struct fsm_state_type *)vinstance;
315 switch (info->status) {
317 strncpy(status, fsm_state->state_name, MGS_LENGTH_DISPLAY_SM);
318 status[MGS_LENGTH_DISPLAY_SM-1]='\0';
319 //uoled_display_fsm(FSM_MAIN, fsm_state->state_name);
323 //uoled_display_fsm(FSM_MAIN, "?");
326 if (strcmp(status,last_status) != 0 ||
327 miliseconds_elapsed_since(&last_sent, 1000)) {
328 uoled_display_fsm(FSM_MAIN, status);
329 clock_gettime(CLOCK_MONOTONIC, &last_sent);
331 strncpy(last_status,status,MGS_LENGTH_DISPLAY_SM);
334 void rcv_fsm_act_cb(const ORTERecvInfo *info, void *vinstance,
335 void *recvCallBackParam)
337 char status[MGS_LENGTH_DISPLAY_SM];
338 static char last_status[MGS_LENGTH_DISPLAY_SM];
339 static struct timespec last_sent;
340 struct fsm_state_type *fsm_state = (struct fsm_state_type *)vinstance;
341 switch (info->status) {
343 strncpy(status, fsm_state->state_name, MGS_LENGTH_DISPLAY_SM);
344 status[MGS_LENGTH_DISPLAY_SM-1]='\0';
350 if (strcmp(status,last_status) != 0 ||
351 miliseconds_elapsed_since(&last_sent, 1000)) {
352 uoled_display_fsm(FSM_ACT, status);
353 clock_gettime(CLOCK_MONOTONIC, &last_sent);
355 strncpy(last_status,status,MGS_LENGTH_DISPLAY_SM);
358 void rcv_fsm_motion_cb(const ORTERecvInfo *info, void *vinstance,
359 void *recvCallBackParam)
361 char status[MGS_LENGTH_DISPLAY_SM];
362 static char last_status[MGS_LENGTH_DISPLAY_SM];
363 static struct timespec last_sent;
364 struct fsm_state_type *fsm_state = (struct fsm_state_type *)vinstance;
365 switch (info->status) {
367 strncpy(status, fsm_state->state_name, MGS_LENGTH_DISPLAY_SM);
368 status[MGS_LENGTH_DISPLAY_SM-1]='\0';
374 if (strcmp(status,last_status) != 0 ||
375 miliseconds_elapsed_since(&last_sent, 1000)) {
376 uoled_display_fsm(FSM_MOVE, status);
377 clock_gettime(CLOCK_MONOTONIC, &last_sent);
379 strncpy(last_status,status,MGS_LENGTH_DISPLAY_SM);
385 int main(int argc, char *argv[])
387 //fd_set read_fd_set;
388 //struct timeval timeout;
392 struct robottype_orte_data orte;
395 signal(SIGINT, sig_handler);
396 signal(SIGTERM, sig_handler);
398 //struct can_frame frame;
399 tty = getenv("DISPLAY_TTY");
402 printf("displayd: enviroment variable 'DISPLAY_TTY' was not set, using default value '%s'.\n", tty);
405 sercom = uoled_sercom_init(tty, NULL);
406 if (strcmp(tty, "/dev/null") == 0 || sercom != NULL) {
408 printf("displayd: init serial communication OK\n");
410 fprintf(stderr, "displayd: init serial communication failed\n");
412 /* Sleep in order to that not be respawn too fast by init */
420 /* orte initialization */
421 if(robottype_roboorte_init(&orte)) {
422 fprintf(stderr, "displayd: Roboorte initialization failed! Exiting...\n");
424 /* Sleep in order to that not be respawn too fast by init */
430 printf("displayd: Roboorte OK\n");
432 /* creating publishers */
433 //robottype_publisher_pwr_voltage_create(&orte, NULL, NULL);
434 //robottype_publisher_motion_status_create(&orte, NULL, NULL);
435 //robottype_publisher_odo_data_create(&orte, NULL, NULL);
436 //robottype_publisher_motion_irc_create(&orte, NULL, NULL);
437 //robottype_publisher_robot_cmd_create(&orte, NULL, NULL);
438 //robottype_publisher_corr_trig_create(&orte, NULL, NULL);
439 //robottype_publisher_corr_distances_create(&orte, NULL, NULL);
440 //robottype_publisher_actuator_status_create(&orte, NULL, NULL);
441 //printf("Publishers OK\n");
443 /* creating subscribers */
444 robottype_subscriber_odo_data_create(&orte, rcv_odo_data_cb, &orte);
445 robottype_subscriber_motion_status_create(&orte, rcv_motion_status_cb, NULL);
446 robottype_subscriber_vidle_status_create(&orte, rcv_vidle_status_cb, NULL);
447 robottype_subscriber_pwr_voltage_create(&orte, rcv_pwr_voltage_cb, &orte);
448 robottype_subscriber_est_pos_best_create(&orte, rcv_est_pos_best_cb, &orte);
449 //robottype_subscriber_pwr_alert_create(&orte, rcv_pwr_alert_cb, &orte);
450 //robottype_subscriber_motion_speed_create(&orte, rcv_motion_speed_cb, &orte);
451 //robottype_subscriber_can_msg_create(&orte, rcv_can_msg_cb, &orte);
452 robottype_subscriber_hokuyo_scan_create(&orte, rcv_hokuyo_scan_cb, &orte);
453 robottype_subscriber_camera_result_create(&orte, rcv_camera_result_cb, &orte);
454 robottype_subscriber_fsm_main_create(&orte, rcv_fsm_main_cb, &orte);
455 robottype_subscriber_fsm_act_create(&orte, rcv_fsm_act_cb, &orte);
456 robottype_subscriber_fsm_motion_create(&orte, rcv_fsm_motion_cb, &orte);
457 robottype_subscriber_robot_cmd_create(&orte, rcv_robot_cmd_cb, &orte);
458 robottype_subscriber_robot_switches_create(&orte, rcv_robot_swicthes_cb, &orte);
460 printf("displayd: subscribers created OK\n");
463 UDE_recieve_cmd_t rcmd;
464 struct pollfd pfd[1] = {{
472 if (strcmp(tty, "/dev/null") != 0) {
473 ret = poll(pfd, 1, 500/*ms*/);
475 ret = uoled_recieve_cmd(&rcmd);
476 /* orte.display_cmd.command=rcmd; */
478 /* ORTEPublicationSend(orte.publication_display_cmd); */
479 /* printf("displayd: publishing command recieved from display [ 0x%2x ]\n", rcmd); */
484 perror("Error: read from display");
488 usleep(500/*ms*/*1000);
492 uoled_display_alive();
496 printf("displayd: closing serial communication...\n");
497 uoled_sercom_close();
498 // printf("displayd: destroying display_cmd publisher...\n");
499 // robottype_publisher_display_cmd_destroy(&orte);
500 printf("displayd: destroying orte instance...\n");
501 robottype_roboorte_destroy(&orte);
504 printf("Waiting 3 seconds\n");
508 printf("displayd: finished!\n");