outline text with black
[fpv.git] / mainboard / rc_proto.c
index 1c1a29f..cca8a78 100644 (file)
@@ -44,6 +44,8 @@
 #include "rc_proto.h"
 #include "xbee_user.h"
 #include "spi_servo.h"
+#include "../common/i2c_commands.h"
+#include "i2c_protocol.h"
 #include "main.h"
 
 #define N_SERVO 6
@@ -56,6 +58,8 @@ struct rc_proto_timers rc_proto_timers = {
        .send_servo_min_ms = 50,
        .send_servo_max_ms = 300,
        .send_power_probe_ms = 500,
+       .send_gps_pos_ms = 500,
+       .send_imu_pos_ms = 100,
        .autobypass_ms = 500,
 };
 
@@ -75,6 +79,10 @@ struct rc_proto_stats_data {
        uint32_t servo_tx;
        uint32_t stats_rx;
        uint32_t stats_tx;
+       uint32_t gps_pos_rx;
+       uint32_t gps_pos_tx;
+       uint32_t imu_pos_rx;
+       uint32_t imu_pos_tx;
        uint32_t echo_ans_latency_sum;
 };
 static struct rc_proto_stats_data stats; /* local stats */
@@ -111,7 +119,7 @@ static uint8_t ack;
 
 /* define tx mode (disabled, send from spi, bypass), rx mode (auto-bypass),
    ... */
-static uint8_t rc_proto_flags;
+static uint16_t rc_proto_flags;
 
 /* callout managing rc_proto (ex: sending of servos periodically) */
 static struct callout rc_proto_timer;
@@ -120,6 +128,8 @@ static struct callout rc_proto_timer;
  * the previous PL value (0 or 4) so we can alternate. */
 int8_t power_level_global = -1;
 
+#define POW_IMU_GPS 4
+
 /* update power level when we receive the answer from DB. The request is sent by
  * rc_proto_rx_power_probe(). */
 static int8_t update_power_level(int8_t retcode, void *frame, unsigned len,
@@ -500,12 +510,84 @@ int8_t rc_proto_send_stats(uint64_t addr, int8_t power)
        return ret;
 }
 
-void rc_proto_set_mode(uint8_t flags)
+/* send a gps_pos message: no answer expected */
+int8_t rc_proto_send_gps_pos(uint64_t addr, int8_t power)
+{
+       struct rc_proto_gps_pos gps_msg;
+       struct xbee_msg msg;
+       uint8_t prio;
+       int8_t ret;
+       uint8_t irq_flags;
+
+       gps_msg.type = RC_PROTO_GPS_POS;
+
+       IRQ_LOCK(irq_flags);
+       gps_msg.valid = !!(imuboard_status.flags & I2C_IMUBOARD_STATUS_GPS_OK);
+       gps_msg.latitude = imuboard_status.latitude;
+       gps_msg.longitude = imuboard_status.longitude;
+       gps_msg.altitude = imuboard_status.altitude;
+       IRQ_UNLOCK(irq_flags);
+
+       msg.iovlen = 1;
+       msg.iov[0].buf = &gps_msg;
+       msg.iov[0].len = sizeof(gps_msg);
+
+       /* set power level */
+       if (power != -1)
+               xbeeapp_send_atcmd("PL", &power, sizeof(power), NULL, NULL);
+
+       /* we also need to lock callout to increment stats */
+       prio = callout_mgr_set_prio(&xbeeboard.intr_cm, XBEE_PRIO);
+       stats.gps_pos_tx++;
+       ret = xbeeapp_send_msg(addr, &msg, NULL, NULL);
+       callout_mgr_restore_prio(&xbeeboard.intr_cm, prio);
+
+       return ret;
+}
+
+/* send a imu_pos message: no answer expected */
+int8_t rc_proto_send_imu_pos(uint64_t addr, int8_t power)
+{
+       struct rc_proto_imu_pos imu_msg;
+       struct xbee_msg msg;
+       uint8_t prio;
+       int8_t ret;
+       uint8_t irq_flags;
+
+       imu_msg.type = RC_PROTO_IMU_POS;
+
+       IRQ_LOCK(irq_flags);
+       imu_msg.valid = !!(imuboard_status.flags & I2C_IMUBOARD_STATUS_IMU_OK);
+       imu_msg.roll = imuboard_status.roll;
+       imu_msg.pitch = imuboard_status.pitch;
+       imu_msg.yaw = imuboard_status.yaw;
+       IRQ_UNLOCK(irq_flags);
+
+       msg.iovlen = 1;
+       msg.iov[0].buf = &imu_msg;
+       msg.iov[0].len = sizeof(imu_msg);
+
+       /* set power level */
+       if (power != -1)
+               xbeeapp_send_atcmd("PL", &power, sizeof(power), NULL, NULL);
+
+       /* we also need to lock callout to increment stats */
+       prio = callout_mgr_set_prio(&xbeeboard.intr_cm, XBEE_PRIO);
+       stats.imu_pos_tx++;
+       ret = xbeeapp_send_msg(addr, &msg, NULL, NULL);
+       callout_mgr_restore_prio(&xbeeboard.intr_cm, prio);
+
+       return ret;
+}
+
+
+
+void rc_proto_set_mode(uint16_t flags)
 {
        rc_proto_flags = flags;
 }
 
-uint8_t rc_proto_get_mode(void)
+uint16_t rc_proto_get_mode(void)
 {
        return rc_proto_flags;
 }
@@ -599,7 +681,7 @@ int rc_proto_rx(struct xbee_recv_hdr *recvframe, unsigned len)
                        struct rc_proto_hello *rch =
                                (struct rc_proto_hello *) recvframe->data;
 
-                       NOTICE(E_USER_XBEE, "recv hello len=%d", rch->datalen);
+                       NOTICE(E_USER_RC_PROTO, "recv hello len=%d", rch->datalen);
                        stats.hello_rx++;
                        return 0;
                }
@@ -609,7 +691,7 @@ int rc_proto_rx(struct xbee_recv_hdr *recvframe, unsigned len)
                                (struct rc_proto_echo_req *) recvframe->data;
                        int8_t power = rce->power;
 
-                       NOTICE(E_USER_XBEE, "recv echo len=%d", rce->datalen);
+                       NOTICE(E_USER_RC_PROTO, "recv echo len=%d", rce->datalen);
                        stats.echo_req_rx++;
 
                        if (rc_proto_send_echo_ans(ntohll(recvframe->srcaddr),
@@ -625,7 +707,7 @@ int rc_proto_rx(struct xbee_recv_hdr *recvframe, unsigned len)
                                (struct rc_proto_echo_ans *) recvframe->data;
                        uint16_t diff;
 
-                       NOTICE(E_USER_XBEE, "recv echo_ans len=%d", rce->datalen);
+                       NOTICE(E_USER_RC_PROTO, "recv echo_ans len=%d", rce->datalen);
                        stats.echo_ans_rx++;
                        diff = get_time_ms() - rce->timestamp;
                        stats.echo_ans_latency_sum += diff;
@@ -637,7 +719,7 @@ int rc_proto_rx(struct xbee_recv_hdr *recvframe, unsigned len)
                        struct rc_proto_power_probe *rcpb =
                                (struct rc_proto_power_probe *) recvframe->data;
 
-                       NOTICE(E_USER_XBEE, "recv power_probe");
+                       NOTICE(E_USER_RC_PROTO, "recv power_probe");
 
                        if (datalen != sizeof(*rcpb))
                                return -1;
@@ -657,7 +739,7 @@ int rc_proto_rx(struct xbee_recv_hdr *recvframe, unsigned len)
                        struct rc_proto_ack *rca =
                                (struct rc_proto_ack *) recvframe->data;
 
-                       NOTICE(E_USER_XBEE, "recv ack, ack=%d", rca->seq);
+                       NOTICE(E_USER_RC_PROTO, "recv ack, ack=%d", rca->seq);
                        stats.ack_rx++;
                        return 0;
                }
@@ -667,7 +749,7 @@ int rc_proto_rx(struct xbee_recv_hdr *recvframe, unsigned len)
                        struct rc_proto_servo *rcs =
                                (struct rc_proto_servo *) recvframe->data;
 
-                       NOTICE(E_USER_XBEE, "recv servo");
+                       NOTICE(E_USER_RC_PROTO, "recv servo");
 
                        if (datalen != RC_PROTO_SERVO_LEN)
                                return -1;
@@ -681,7 +763,7 @@ int rc_proto_rx(struct xbee_recv_hdr *recvframe, unsigned len)
                        struct rc_proto_stats *rcs =
                                (struct rc_proto_stats *) recvframe->data;
 
-                       NOTICE(E_USER_XBEE, "recv stats");
+                       NOTICE(E_USER_RC_PROTO, "recv stats");
 
                        if (datalen != sizeof(*rcs) + sizeof(peer_stats))
                                return -1;
@@ -691,6 +773,37 @@ int rc_proto_rx(struct xbee_recv_hdr *recvframe, unsigned len)
                        return 0;
                }
 
+               /* received by the radio controller */
+               case RC_PROTO_GPS_POS: {
+                       struct rc_proto_gps_pos *rcmsg =
+                               (struct rc_proto_gps_pos *) recvframe->data;
+
+                       if (datalen != sizeof(*rcmsg))
+                               return -1;
+
+                       stats.gps_pos_rx++;
+                       NOTICE(E_USER_RC_PROTO, "GPS received valid=%d %"PRIu32" %"
+                               PRIu32" %"PRIu32,
+                               rcmsg->valid, rcmsg->latitude, rcmsg->longitude,
+                               rcmsg->altitude);
+                       return 0;
+               }
+
+               /* received by the radio controller */
+               case RC_PROTO_IMU_POS: {
+                       struct rc_proto_imu_pos *rcmsg =
+                               (struct rc_proto_imu_pos *) recvframe->data;
+
+                       if (datalen != sizeof(*rcmsg))
+                               return -1;
+
+                       stats.imu_pos_rx++;
+                       NOTICE(E_USER_RC_PROTO,
+                               "IMU received %d %d %d",
+                               rcmsg->roll, rcmsg->pitch, rcmsg->yaw);
+                       return 0;
+               }
+
                default:
                        return -1;
        }
@@ -706,6 +819,8 @@ static void rc_proto_cb(struct callout_mgr *cm, struct callout *tim, void *arg)
        static uint16_t prev_stats_send;
        static uint16_t prev_compute_pow;
        static uint16_t prev_power_probe;
+       static uint16_t prev_gps_pos;
+       static uint16_t prev_imu_pos;
        static uint8_t pow_probe;
        uint16_t t, diff;
 
@@ -727,6 +842,24 @@ static void rc_proto_cb(struct callout_mgr *cm, struct callout *tim, void *arg)
                }
        }
 
+       /* send gps periodically */
+       if (rc_proto_flags & RC_PROTO_FLAGS_TX_GPS_POS) {
+               diff = t - prev_gps_pos;
+               if (diff > rc_proto_timers.send_gps_pos_ms) {
+                       rc_proto_send_gps_pos(rc_proto_dstaddr, POW_IMU_GPS);
+                       prev_gps_pos = t;
+               }
+       }
+
+       /* send imu periodically */
+       if (rc_proto_flags & RC_PROTO_FLAGS_TX_IMU_POS) {
+               diff = t - prev_imu_pos;
+               if (diff > rc_proto_timers.send_imu_pos_ms) {
+                       rc_proto_send_imu_pos(rc_proto_dstaddr, POW_IMU_GPS);
+                       prev_imu_pos = t;
+               }
+       }
+
        /* on wing, auto bypass servos if no commands since some time */
        if (rc_proto_flags & RC_PROTO_FLAGS_RX_AUTOBYPASS) {
                diff = t - servo_rx.time;
@@ -755,47 +888,39 @@ static void rc_proto_cb(struct callout_mgr *cm, struct callout *tim, void *arg)
        callout_schedule(cm, tim, 0);
 }
 
-void rc_proto_dump_stats(void)
+static void __dump_stats(struct rc_proto_stats_data *s)
 {
-       printf_P(PSTR("rc_proto stats LOCAL\r\n"));
-       printf_P(PSTR("  hello_tx: %"PRIu32"\r\n"), stats.hello_tx);
-       printf_P(PSTR("  hello_rx: %"PRIu32"\r\n"), stats.hello_rx);
-       printf_P(PSTR("  echo_req_rx: %"PRIu32"\r\n"), stats.echo_req_rx);
-       printf_P(PSTR("  echo_req_tx: %"PRIu32"\r\n"), stats.echo_req_tx);
-       printf_P(PSTR("  echo_ans_rx: %"PRIu32"\r\n"), stats.echo_ans_rx);
-       printf_P(PSTR("  echo_ans_tx: %"PRIu32"\r\n"), stats.echo_ans_tx);
-       printf_P(PSTR("  power_probe_rx: %"PRIu32"\r\n"), stats.power_probe_rx);
-       printf_P(PSTR("  power_probe_tx: %"PRIu32"\r\n"), stats.power_probe_tx);
-       printf_P(PSTR("  ack_rx: %"PRIu32"\r\n"), stats.ack_rx);
-       printf_P(PSTR("  ack_tx: %"PRIu32"\r\n"), stats.ack_tx);
-       printf_P(PSTR("  servo_rx: %"PRIu32"\r\n"), stats.servo_rx);
-       printf_P(PSTR("  servo_tx: %"PRIu32"\r\n"), stats.servo_tx);
-       printf_P(PSTR("  stats_rx: %"PRIu32"\r\n"), stats.stats_rx);
-       printf_P(PSTR("  stats_tx: %"PRIu32"\r\n"), stats.stats_tx);
-       if (stats.echo_ans_rx != 0) {
+       printf_P(PSTR("  hello_tx: %"PRIu32"\r\n"), s->hello_tx);
+       printf_P(PSTR("  hello_rx: %"PRIu32"\r\n"), s->hello_rx);
+       printf_P(PSTR("  echo_req_rx: %"PRIu32"\r\n"), s->echo_req_rx);
+       printf_P(PSTR("  echo_req_tx: %"PRIu32"\r\n"), s->echo_req_tx);
+       printf_P(PSTR("  echo_ans_rx: %"PRIu32"\r\n"), s->echo_ans_rx);
+       printf_P(PSTR("  echo_ans_tx: %"PRIu32"\r\n"), s->echo_ans_tx);
+       printf_P(PSTR("  power_probe_rx: %"PRIu32"\r\n"), s->power_probe_rx);
+       printf_P(PSTR("  power_probe_tx: %"PRIu32"\r\n"), s->power_probe_tx);
+       printf_P(PSTR("  ack_rx: %"PRIu32"\r\n"), s->ack_rx);
+       printf_P(PSTR("  ack_tx: %"PRIu32"\r\n"), s->ack_tx);
+       printf_P(PSTR("  servo_rx: %"PRIu32"\r\n"), s->servo_rx);
+       printf_P(PSTR("  servo_tx: %"PRIu32"\r\n"), s->servo_tx);
+       printf_P(PSTR("  stats_rx: %"PRIu32"\r\n"), s->stats_rx);
+       printf_P(PSTR("  stats_tx: %"PRIu32"\r\n"), s->stats_tx);
+       printf_P(PSTR("  gps_pos_rx: %"PRIu32"\r\n"), s->gps_pos_rx);
+       printf_P(PSTR("  gps_pos_tx: %"PRIu32"\r\n"), s->gps_pos_tx);
+       printf_P(PSTR("  imu_pos_rx: %"PRIu32"\r\n"), s->imu_pos_rx);
+       printf_P(PSTR("  imu_pos_tx: %"PRIu32"\r\n"), s->imu_pos_tx);
+       if (s->echo_ans_rx != 0) {
                printf_P(PSTR("  echo_ans_latency_ms: %"PRIu32"\r\n"),
-                       stats.echo_ans_latency_sum / stats.echo_ans_rx);
+                       s->echo_ans_latency_sum / s->echo_ans_rx);
        }
+}
+
+void rc_proto_dump_stats(void)
+{
+       printf_P(PSTR("rc_proto stats LOCAL\r\n"));
+       __dump_stats(&stats);
 
        printf_P(PSTR("rc_proto stats PEER\r\n"));
-       printf_P(PSTR("  hello_tx: %"PRIu32"\r\n"), peer_stats.hello_tx);
-       printf_P(PSTR("  hello_rx: %"PRIu32"\r\n"), peer_stats.hello_rx);
-       printf_P(PSTR("  echo_req_rx: %"PRIu32"\r\n"), peer_stats.echo_req_rx);
-       printf_P(PSTR("  echo_req_tx: %"PRIu32"\r\n"), peer_stats.echo_req_tx);
-       printf_P(PSTR("  echo_ans_rx: %"PRIu32"\r\n"), peer_stats.echo_ans_rx);
-       printf_P(PSTR("  echo_ans_tx: %"PRIu32"\r\n"), peer_stats.echo_ans_tx);
-       printf_P(PSTR("  power_probe_rx: %"PRIu32"\r\n"), peer_stats.power_probe_rx);
-       printf_P(PSTR("  power_probe_tx: %"PRIu32"\r\n"), peer_stats.power_probe_tx);
-       printf_P(PSTR("  ack_rx: %"PRIu32"\r\n"), peer_stats.ack_rx);
-       printf_P(PSTR("  ack_tx: %"PRIu32"\r\n"), peer_stats.ack_tx);
-       printf_P(PSTR("  servo_rx: %"PRIu32"\r\n"), peer_stats.servo_rx);
-       printf_P(PSTR("  servo_tx: %"PRIu32"\r\n"), peer_stats.servo_tx);
-       printf_P(PSTR("  stats_rx: %"PRIu32"\r\n"), peer_stats.stats_rx);
-       printf_P(PSTR("  stats_tx: %"PRIu32"\r\n"), peer_stats.stats_tx);
-       if (peer_stats.echo_ans_rx != 0) {
-               printf_P(PSTR("  echo_ans_latency_ms: %"PRIu32"\r\n"),
-                       peer_stats.echo_ans_latency_sum / peer_stats.echo_ans_rx);
-       }
+       __dump_stats(&peer_stats);
 }
 
 void rc_proto_reset_stats(void)