]> Pileus Git - ~andy/csm213a-hw/blobdiff - hw2/main_comm.c
Make control script more configurable
[~andy/csm213a-hw] / hw2 / main_comm.c
index e31fc562f22ed0412e90e85ebfa7fc9402dcf069..ed864ccab1ba230a7bc03fc077834889ff4e6b49 100644 (file)
@@ -8,11 +8,44 @@
 #include "main_time.h"
 #include "main_emit.h"
 
+/**
+ * Communcation overview:
+ *
+ *     Initialization:
+ *        bbb --init1-->  mbed1
+ *        bbb --init2-->  mbed1 --init2---> mbed2
+ *
+ *     Time sync:
+ *        bbb             mbed1 ---sync---> mbed2
+ *        bbb             mbed1 <--sync---- mbed2
+ *
+ *     Event Receive:
+ *        bbb <--event1-- mbed1             mbed2
+ *        bbb <--event2-- mbed1 <--event2-- mbed2
+ *
+ * Initialization:
+ *     Each mbed is initialized by the BBB by receiving an initialization
+ *     message.  The Device ID must be non-zero, and is saved for future
+ *     messages. If the device is already initialized and a recevied Device ID
+ *     does not match the configured Device ID, the messages is relayed to the
+ *     second mbed.
+ *
+ * Event receive:
+ *     When receiving events, an event message is sent from the mbed to the
+ *     bbb. If the mbed receiving the event is not Device 1, the message is
+ *     sent to mbed1 instead of the bbb.
+ *
+ * Debug ports:
+ *     1. Init messages may be received from the host instead of the bbb
+ *     2. Event messages may be sent to the host in addition to the bbb
+ */
+
 /***************************
  * Communication functions *
  ***************************/
 
-static uint32_t comm_device_id   = 0;
+static int      comm_device_id   = 0;
+static int      comm_relay_mode  = 0;
 
 const  uint64_t comm_sync_delay  = NSEC_PER_SEC / 100;
 static uint64_t comm_sync_due    = 0;
@@ -24,30 +57,16 @@ static sirq_t  *comm_sirq_mbed   = 0;
 static tdma_t  *comm_tdma_rcv    = 0;
 static tdma_t  *comm_tdma_xmt    = 0;
 
-/**
- * Initialization
- */
-void comm_init(sirq_t *dbg, sirq_t *bbb, sirq_t *mbed,
-               tdma_t *rcv, tdma_t *xmt)
-{
-       comm_sirq_dbg  = dbg;
-       comm_sirq_bbb  = bbb;
-       comm_sirq_mbed = mbed;
-
-       comm_tdma_rcv  = rcv;
-       comm_tdma_xmt  = xmt;
-}
-
 /**
  * Convert world to local time
  */
-uint64_t comm_read_time(ntime_t time)
+static uint64_t comm_read_time(ntime_t time)
 {
        return ((uint64_t)time.seconds) * NSEC_PER_SEC
             + ((uint64_t)time.nanosec);
 }
 
-ntime_t comm_write_time(uint64_t time)
+static ntime_t comm_write_time(uint64_t time)
 {
        ntime_t buf = {};
        buf.seconds = time / NSEC_PER_SEC;
@@ -55,7 +74,7 @@ ntime_t comm_write_time(uint64_t time)
        return buf;
 }
 
-int comm_time_stamp(tdma_t *port, uint64_t *local, uint64_t *world,
+static int comm_time_stamp(tdma_t *port, uint64_t *local, uint64_t *world,
                const char *msg)
 {
        int valid = tdma_stamp(port, local);
@@ -70,18 +89,25 @@ int comm_time_stamp(tdma_t *port, uint64_t *local, uint64_t *world,
 }
 
 /**
- * Output initialization message init message
+ * Initialization
  */
-void comm_send_init(uint16_t device, uint64_t local)
+void comm_init(sirq_t *dbg, sirq_t *bbb, sirq_t *mbed,
+               tdma_t *rcv, tdma_t *xmt)
 {
+       comm_sirq_dbg  = dbg;
+       comm_sirq_bbb  = bbb;
+       comm_sirq_mbed = mbed;
+
+       comm_tdma_rcv  = rcv;
+       comm_tdma_xmt  = xmt;
 }
 
 /**
  * Output time sync message
  */
-void comm_send_sync(sirq_t *port, uint64_t now)
+void comm_send_sync(uint64_t local)
 {
-       if (comm_sync_due == 0 || now < comm_sync_due)
+       if (comm_sync_due == 0 || local < comm_sync_due)
                return; // not ready
 
        // Message data
@@ -94,28 +120,33 @@ void comm_send_sync(sirq_t *port, uint64_t now)
        head.length = sizeof(body);
        head.cksum  = 0; // todo
 
+       sirq_write(comm_sirq_mbed, &head, sizeof(head));
+
+       // Capture transmit time
        tdma_stop(comm_tdma_rcv, 0);
        tdma_start(comm_tdma_xmt);
 
-       sirq_write(port, &head, sizeof(head));
+       sirq_transmit(comm_sirq_mbed);
 
        tdma_stop(comm_tdma_xmt, 100);
        tdma_start(comm_tdma_rcv);
 
        // Save transmit time
-       uint64_t local = 0, world = 0;
-       comm_time_stamp(comm_tdma_xmt, &local, &world,
+       uint64_t xmt_local = 0, xmt_world = 0;
+       comm_time_stamp(comm_tdma_xmt, &xmt_local, &xmt_world,
                        "sync time transmit");
 
        // Debug output
        //sirq_printf("sync time transmit\r\n");
-       //time_printf("  local", local);
-       //time_printf("  world", world);
+       //time_printf("  local", xmt_local);
+       //time_printf("  world", xmt_world);
 
        // Write body with updated time and send
-       body.time = comm_write_time(world);
+       body.time = comm_write_time(xmt_world);
 
-       sirq_write(port, &body, sizeof(body));
+       sirq_write(comm_sirq_mbed, &body, sizeof(body));
+
+       sirq_transmit(comm_sirq_mbed);
 
        // Queue next transmit time
        comm_sync_due  = 0;
@@ -126,7 +157,7 @@ void comm_send_sync(sirq_t *port, uint64_t now)
  *   event: id of the received event
  *   time:  compensated timestamp of the event
  */
-void comm_send_event(sirq_t *port, uint16_t event, uint64_t local)
+void comm_send_event(uint16_t event, uint64_t local)
 {
        //time_printf("event received", local);
 
@@ -151,50 +182,74 @@ void comm_send_event(sirq_t *port, uint16_t event, uint64_t local)
        body.local  = ltime;
 
        // Transmit message to BBB
-       sirq_write(port, &head, sizeof(head));
-       sirq_write(port, &body, sizeof(body));
+       if (comm_relay_mode) {
+               sirq_write(comm_sirq_mbed, &head, sizeof(head));
+               sirq_write(comm_sirq_mbed, &body, sizeof(body));
+       } else {
+               sirq_write(comm_sirq_bbb,  &head, sizeof(head));
+               sirq_write(comm_sirq_bbb,  &body, sizeof(body));
+       }
 }
 
 /**
  * Handle init message
  */
-void comm_handle_init(int msgid, init_msg_t *body)
+void comm_handle_init(header_t *head, init_msg_t *body)
 {
+       // Relay initialization from bbb to mbed
+       if (comm_device_id && body->device != comm_device_id) {
+               //sirq_printf("relaying init\r\n");
+
+               sirq_write(comm_sirq_mbed, head, sizeof(*head));
+               sirq_write(comm_sirq_mbed, body, sizeof(*body));
+
+               // Normally we transmit during the time sync but
+               // if we haven't started syncing yet, we need to
+               // push out the message now.
+               if (!comm_sync_due)
+                       sirq_transmit(comm_sirq_mbed);
+               return;
+       }
+
+       // Debug output
        sirq_printf("initialize: %s %s %s %s %s\r\n",
-               body->valid & MSG_VALID_DEVICE ? "DEV"    : "dev",
-               body->valid & MSG_VALID_START  ? "START"  : "start",
-               body->valid & MSG_VALID_PERIOD ? "PERIOD" : "period",
-               body->valid & MSG_VALID_WORLD  ? "WORLD"  : "world",
-               body->valid & MSG_VALID_SYNC   ? "SYNC"   : "sync");
+               body->control & MSG_CTL_VALID_DEVICE ? "DEV"    : "dev",
+               body->control & MSG_CTL_VALID_START  ? "START"  : "start",
+               body->control & MSG_CTL_VALID_PERIOD ? "PERIOD" : "period",
+               body->control & MSG_CTL_VALID_WORLD  ? "WORLD"  : "world",
+               body->control & MSG_CTL_RELAY_MODE   ? "RELAY"  : "relay",
+               body->control & MSG_CTL_BEGIN_SYNC   ? "SYNC"   : "sync");
        sirq_printf("  dev    -- %d\r\n", body->device);
        time_printf("  start ", comm_read_time(body->start));
        time_printf("  period", comm_read_time(body->period));
        time_printf("  world ", comm_read_time(body->world));
 
-       if (body->valid & MSG_VALID_DEVICE)
+       // Validate message parts and initialize
+       if (body->control & MSG_CTL_VALID_DEVICE)
                comm_device_id = body->device;
 
-       if (body->valid & MSG_VALID_START ||
-           body->valid & MSG_VALID_PERIOD) {
-               uint64_t start  = comm_read_time(body->start);
-               uint64_t period = comm_read_time(body->period);
-               emit_enable(start, period);
-       }
+       if (body->control & MSG_CTL_VALID_START)
+               emit_set_start(comm_read_time(body->start));
 
-       if (body->valid & MSG_VALID_WORLD) {
-               uint64_t world = comm_read_time(body->world);
-               uint64_t local = tdma_time();
-               time_ext_init(local, world);
-       }
+       if (body->control & MSG_CTL_VALID_PERIOD)
+               emit_set_period(comm_read_time(body->period));
+
+       if (body->control & MSG_CTL_VALID_WORLD)
+               time_ext_init(tdma_time(), comm_read_time(body->world));
 
-       if (body->valid & MSG_VALID_SYNC)
+       if (body->control & MSG_CTL_RELAY_MODE)
+               comm_relay_mode = 1;
+       else
+               comm_relay_mode = 0;
+
+       if (body->control & MSG_CTL_BEGIN_SYNC)
                comm_sync_due = tdma_time() + comm_sync_delay;
 }
 
 /**
  * Handle sync message
  */
-void comm_handle_sync(int msgid, sync_msg_t *body)
+void comm_handle_sync(header_t *head, sync_msg_t *body)
 {
        // Read receive timestamp
        uint64_t local = 0, world = 0;
@@ -223,9 +278,7 @@ void comm_handle_sync(int msgid, sync_msg_t *body)
  */
 void comm_handle_event(header_t *head, event_msg_t *body)
 {
-       // Relay event from mbed to bbb
-       if (comm_device_id == 1) {
-               sirq_write(comm_sirq_bbb, &head, sizeof(head));
-               sirq_write(comm_sirq_bbb, &body, sizeof(body));
-       }
+       // Relay events from other mbeds
+       sirq_write(comm_sirq_bbb, head, sizeof(*head));
+       sirq_write(comm_sirq_bbb, body, sizeof(*body));
 }