]> rtime.felk.cvut.cz Git - eurobot/public.git/blobdiff - src/displayd/displayd.c
Unify ORTE initialization
[eurobot/public.git] / src / displayd / displayd.c
index f2654111fb55f9ed9bb0b5685281d765a695eecb..1c3cd6b09d8dd6787b8a6d1b5ef13ab5523495a9 100644 (file)
@@ -21,6 +21,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <stdbool.h>
 
 struct sercom_data* sercom;
 int interrupt = 0;
@@ -61,13 +62,18 @@ int timespec_subtract (struct timespec *result,
   return x->tv_sec < y->tv_sec;
 }
 
-int miliseconds_since(struct timespec *t)
+bool miliseconds_elapsed_since(struct timespec *t, unsigned miliseconds)
 {
        struct timespec now, diff;
+       unsigned long long elapsed;
+
+       if (t->tv_sec == 0 && t->tv_nsec == 0)
+               return true;    /* Always elapsed after program start */
 
        clock_gettime(CLOCK_MONOTONIC, &now);
-       timespec_subtract(&diff, t, &now);
-       return diff.tv_sec * 1000 + diff.tv_nsec/1000000;       
+       timespec_subtract(&diff, &now, t);
+       elapsed = diff.tv_sec * 1000 + diff.tv_nsec/1000000;
+       return elapsed > miliseconds;
 }
 
 
@@ -90,8 +96,8 @@ void rcv_pwr_voltage_cb (const ORTERecvInfo *info, void *vinstance,
                        break;
        }
        if (status != last_status ||
-           miliseconds_since(&last_sent) > 1000) {
-               uoled_display_status(PWR, STATUS_OK);
+           miliseconds_elapsed_since(&last_sent, 1000)) {
+               uoled_display_status(PWR, status);
                clock_gettime(CLOCK_MONOTONIC, &last_sent);
        }
        last_status = status;
@@ -114,22 +120,75 @@ void rcv_odo_data_cb(const ORTERecvInfo *info, void *vinstance,
        }
        /* Neni potreba aktualizovat stav na displeji 25x za sekundu */
        if (status != last_status ||
-           miliseconds_since(&last_sent) > 1000) {
-               uoled_display_status(ODO, STATUS_OK);
+           miliseconds_elapsed_since(&last_sent, 1000)) {
+               uoled_display_status(ODO, status);
                clock_gettime(CLOCK_MONOTONIC, &last_sent);
        }
        last_status = status;
 }
 
-void rcv_motion_irc_cb(const ORTERecvInfo *info, void *vinstance,
+void rcv_robot_cmd_cb(const ORTERecvInfo *info, void *vinstance,
                         void *recvCallBackParam)
 {
        UDE_hw_status_t status = STATUS_FAILED;
        static UDE_hw_status_t last_status;
        static struct timespec last_sent;
+       struct robot_cmd_type *instance = (struct robot_cmd_type *)vinstance;
+
        switch (info->status) {
                case NEW_DATA:
-                       status = STATUS_OK;
+                       if (instance->start_condition)
+                               status = STATUS_WARNING; /* Start plug must be plugged before competition start */
+                       else
+                               status = STATUS_OK;
+                       break;
+               case DEADLINE:
+                       status = STATUS_FAILED;
+                       break;
+       }
+       if (status != last_status ||
+           miliseconds_elapsed_since(&last_sent, 500)) {
+               uoled_display_status(STA, status);
+               clock_gettime(CLOCK_MONOTONIC, &last_sent);
+       }
+       last_status = status;
+}
+
+void rcv_robot_swicthes_cb(const ORTERecvInfo *info, void *vinstance,
+                          void *recvCallBackParam)
+{
+       UDE_hw_status_t status = STATUS_FAILED;
+       static char last_color;
+       static struct timespec last_sent;
+       struct robot_switches_type *instance = (struct robot_switches_type *)vinstance;
+
+       switch (info->status) {
+               case NEW_DATA:
+                       if (instance->team_color != last_color ||
+                           miliseconds_elapsed_since(&last_sent, 1000)) {
+                               uoled_display_color(instance->team_color);
+                               clock_gettime(CLOCK_MONOTONIC, &last_sent);
+                       }
+                       last_color = instance->team_color;
+               case DEADLINE:
+                       status = STATUS_FAILED;
+                       break;
+       }
+}
+
+void rcv_motion_status_cb(const ORTERecvInfo *info, void *vinstance,
+                        void *recvCallBackParam)
+{
+       struct motion_status_type *m = (struct motion_status_type *)vinstance;
+       UDE_hw_status_t status = STATUS_FAILED;
+       static UDE_hw_status_t last_status;
+       static struct timespec last_sent;
+       switch (info->status) {
+               case NEW_DATA:
+                       if (m->err_left == 0 && m->err_right == 0)
+                               status = STATUS_OK;
+                       else
+                               status = STATUS_WARNING;
                        break;
                case DEADLINE:
                        status = STATUS_FAILED;
@@ -137,8 +196,35 @@ void rcv_motion_irc_cb(const ORTERecvInfo *info, void *vinstance,
        }
        /* Neni potreba aktualizovat stav na displeji 25x za sekundu */
        if (status != last_status ||
-           miliseconds_since(&last_sent) > 1000) {
-               uoled_display_status(MOT, STATUS_OK);
+           miliseconds_elapsed_since(&last_sent, 1000)) {
+               uoled_display_status(MOT, status);
+               clock_gettime(CLOCK_MONOTONIC, &last_sent);
+       }
+       last_status = status;
+}
+
+void rcv_vidle_status_cb(const ORTERecvInfo *info, void *vinstance,
+                        void *recvCallBackParam)
+{
+       struct vidle_status_type *m = (struct vidle_status_type *)vinstance;
+       UDE_hw_status_t status = STATUS_FAILED;
+       static UDE_hw_status_t last_status;
+       static struct timespec last_sent;
+       switch (info->status) {
+               case NEW_DATA:
+                       if (m->flags == 0)
+                               status = STATUS_OK;
+                       else
+                               status = STATUS_WARNING;
+                       break;
+               case DEADLINE:
+                       status = STATUS_FAILED;
+                       break;
+       }
+       /* Neni potreba aktualizovat stav na displeji 25x za sekundu */
+       if (status != last_status ||
+           miliseconds_elapsed_since(&last_sent, 1000)) {
+               uoled_display_status(VID, status);
                clock_gettime(CLOCK_MONOTONIC, &last_sent);
        }
        last_status = status;
@@ -150,21 +236,34 @@ void rcv_camera_result_cb(const ORTERecvInfo *info, void *vinstance,
        UDE_hw_status_t status = STATUS_FAILED;
        static UDE_hw_status_t last_status;
        static struct timespec last_sent;
-       //struct camera_result_type *instance = (struct camera_result_type *)vinstance;
+       struct camera_result_type *instance = (struct camera_result_type *)vinstance;
+       char s, c;
        switch (info->status) {
                case NEW_DATA:
-                       status = STATUS_OK;
+                       if (instance->error == 0)
+                               status = STATUS_OK;
+                       else
+                               status = STATUS_WARNING;
                        break;
                case DEADLINE:
                        status = STATUS_FAILED;
                        break;
        }
        if (status != last_status ||
-           miliseconds_since(&last_sent) > 1000) {
-               uoled_display_status(CAM, STATUS_OK);
+           miliseconds_elapsed_since(&last_sent, 1000)) {
+               uoled_display_status(CAM, status);
                clock_gettime(CLOCK_MONOTONIC, &last_sent);
        }
        last_status = status;
+
+       if (status == STATUS_OK) {
+               s = (instance->side >= 0 && instance->side < 10) ?
+                       '0'+instance->side : 'E';
+               c = (instance->center >= 0 && instance->center < 10) ?
+                       '0'+instance->center : 'E';
+       } else
+               s = c = '-';
+       uoled_display_corns(s, c);
 }
 
 void rcv_hokuyo_scan_cb(const ORTERecvInfo *info, void *vinstance,
@@ -183,8 +282,8 @@ void rcv_hokuyo_scan_cb(const ORTERecvInfo *info, void *vinstance,
                        break;
        }
        if (status != last_status ||
-           miliseconds_since(&last_sent) > 1000) {
-               uoled_display_status(HOK, STATUS_OK);
+           miliseconds_elapsed_since(&last_sent, 1000)) {
+               uoled_display_status(HOK, status);
                clock_gettime(CLOCK_MONOTONIC, &last_sent);
        }
        last_status = status;
@@ -199,7 +298,6 @@ void rcv_est_pos_best_cb (const ORTERecvInfo *info, void *vinstance,
        struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
         switch (info->status) {
                case NEW_DATA:
-                       uoled_display_position(orte_data->est_pos_best.x, orte_data->est_pos_best.y, orte_data->est_pos_best.phi);
                        status = STATUS_OK;
                        break;
                case DEADLINE:
@@ -207,8 +305,10 @@ void rcv_est_pos_best_cb (const ORTERecvInfo *info, void *vinstance,
                        break;
        }
        if (status != last_status ||
-           miliseconds_since(&last_sent) > 1000) {
-               uoled_display_status(ODO, STATUS_OK);
+           miliseconds_elapsed_since(&last_sent, 100)) {
+               uoled_display_status(APP, status);
+               if (status == STATUS_OK)
+                       uoled_display_position(orte_data->est_pos_best.x, orte_data->est_pos_best.y, orte_data->est_pos_best.phi);
                clock_gettime(CLOCK_MONOTONIC, &last_sent);
        }
        last_status = status;
@@ -233,7 +333,7 @@ void rcv_fsm_main_cb(const ORTERecvInfo *info, void *vinstance,
                         break;
         }
        if (strcmp(status,last_status) != 0 ||
-           miliseconds_since(&last_sent) > 1000) {
+           miliseconds_elapsed_since(&last_sent, 1000)) {
                 uoled_display_fsm(FSM_MAIN, status);
                clock_gettime(CLOCK_MONOTONIC, &last_sent);
        }
@@ -257,7 +357,7 @@ void rcv_fsm_act_cb(const ORTERecvInfo *info, void *vinstance,
                         break;
         }
        if (strcmp(status,last_status) != 0 ||
-           miliseconds_since(&last_sent) > 1000) {
+           miliseconds_elapsed_since(&last_sent, 1000)) {
                 uoled_display_fsm(FSM_ACT, status);
                clock_gettime(CLOCK_MONOTONIC, &last_sent);
        }
@@ -281,7 +381,7 @@ void rcv_fsm_motion_cb(const ORTERecvInfo *info, void *vinstance,
                         break;
         }
        if (strcmp(status,last_status) != 0 ||
-           miliseconds_since(&last_sent) > 1000) {
+           miliseconds_elapsed_since(&last_sent, 1000)) {
                 uoled_display_fsm(FSM_MOVE, status);
                clock_gettime(CLOCK_MONOTONIC, &last_sent);
        }
@@ -289,7 +389,7 @@ void rcv_fsm_motion_cb(const ORTERecvInfo *info, void *vinstance,
 }
 
 
-
+struct robottype_orte_data orte;
 
 int main(int argc, char *argv[])
 {
@@ -298,7 +398,6 @@ int main(int argc, char *argv[])
        int ret;
        //int size;
 
-       struct robottype_orte_data orte;
        char * tty;
 
        signal(SIGINT, sig_handler);
@@ -312,20 +411,26 @@ int main(int argc, char *argv[])
        }
 
        sercom = uoled_sercom_init(tty, NULL);
-       if (strcmp(tty, "/dev/null") != 0) {
+       if (strcmp(tty, "/dev/null") == 0 || sercom != NULL) {
        // :wq
                printf("displayd: init serial communication OK\n");
        } else {
-               printf("displayd: init serial communication failed\n");
-               //return 1;
+               fprintf(stderr, "displayd: init serial communication failed\n");
+//#ifdef COMPETITION
+               /* Sleep in order to that not be respawn too fast by init */
+               sleep(3);
+               return 1;
+//#endif
        }
 
-       orte.strength = 1;
-
        /* orte initialization */
        if(robottype_roboorte_init(&orte)) {
-               printf("displayd: Roboorte initialization failed! Exiting...\n");
-               return -1;
+               fprintf(stderr, "displayd: Roboorte initialization failed! Exiting...\n");
+#ifdef COMPETITION
+               /* Sleep in order to that not be respawn too fast by init */
+               sleep(3);
+#endif
+               return 1;
        }
        else
                printf("displayd: Roboorte OK\n");
@@ -343,7 +448,8 @@ int main(int argc, char *argv[])
 
        /* creating subscribers */
        robottype_subscriber_odo_data_create(&orte, rcv_odo_data_cb, &orte);
-       robottype_subscriber_motion_irc_create(&orte, rcv_motion_irc_cb, &orte);
+       robottype_subscriber_motion_status_create(&orte, rcv_motion_status_cb, NULL);
+       robottype_subscriber_vidle_status_create(&orte, rcv_vidle_status_cb, NULL);
        robottype_subscriber_pwr_voltage_create(&orte, rcv_pwr_voltage_cb, &orte);
        robottype_subscriber_est_pos_best_create(&orte, rcv_est_pos_best_cb, &orte);
        //robottype_subscriber_pwr_alert_create(&orte, rcv_pwr_alert_cb, &orte);
@@ -354,6 +460,8 @@ int main(int argc, char *argv[])
        robottype_subscriber_fsm_main_create(&orte, rcv_fsm_main_cb, &orte);
        robottype_subscriber_fsm_act_create(&orte, rcv_fsm_act_cb, &orte);
        robottype_subscriber_fsm_motion_create(&orte, rcv_fsm_motion_cb, &orte);
+       robottype_subscriber_robot_cmd_create(&orte, rcv_robot_cmd_cb, &orte);
+       robottype_subscriber_robot_switches_create(&orte, rcv_robot_swicthes_cb, &orte);
 
        printf("displayd: subscribers created OK\n");
 
@@ -370,13 +478,17 @@ int main(int argc, char *argv[])
                if (strcmp(tty, "/dev/null") != 0) {
                        ret = poll(pfd, 1, 500/*ms*/);
                        if (ret > 0) {
-                               rcmd = uoled_recieve_cmd();
-                               orte.display_cmd.command=rcmd;
-                               if (! rcmd){
-                                       ORTEPublicationSend(orte.publication_display_cmd);
-                                       printf("displayd: publishing command recieved from display [ 0x%2x ]\n", rcmd);
+                               ret = uoled_recieve_cmd(&rcmd);
+/*                             orte.display_cmd.command=rcmd; */
+/*                             if (! rcmd){ */
+/*                                     ORTEPublicationSend(orte.publication_display_cmd); */
+/*                                     printf("displayd: publishing command recieved from display [ 0x%2x ]\n", rcmd); */
 
-                               }
+/*                             } */
+                       }
+                       if (ret < 0) {
+                               perror("Error: read from display");
+                               break;
                        }
                } else {
                        usleep(500/*ms*/*1000);
@@ -394,6 +506,11 @@ int main(int argc, char *argv[])
        printf("displayd: destroying orte instance...\n");
        robottype_roboorte_destroy(&orte);
 
+       if (!interrupt) {
+               printf("Waiting 3 seconds\n");
+               sleep(3);
+       }
+
        printf("displayd: finished!\n");
        return 0;
 }