]> Pileus Git - ~andy/csm213a-hw/blobdiff - hw2/main.cpp
Debug relayed initialization
[~andy/csm213a-hw] / hw2 / main.cpp
index a43bc8e80c4b406e1165624a614ff0b46c847d1a..d03b3f312cc3aa843290485b338f7f333bf65859 100644 (file)
-#include "mbed.h"\r
-\r
-DigitalOut led1(LED1);\r
-DigitalOut led2(LED2);\r
-\r
-int main(int argc, char **argv)\r
-{\r
-    while (1) {\r
-        led1 = 1; led2 = 0; wait(0.1);\r
-        led1 = 0; led2 = 1; wait(0.1);\r
-    }\r
-}\r
+#include "messages.h"
+
+#include "mbed.h"
+#include "serial_irq.h"
+#include "serial_dma.h"
+#include "timer_dma.h"
+
+#include "main_time.h"
+#include "main_emit.h"
+#include "main_comm.h"
+
+/**
+ * Mode of operation:
+ *   Devices 1 and 2 synchronize clocks using serial messages.
+ *
+ *   1. Each serial message timestamped using the hardware timer capture
+ *      registers in both the sender and receiver.
+ *   2. The sender transmits the send timestamp during the next time-sync
+ *      message.
+ *   3. The receiver then compares the senders timestamp with it's own
+ *      timestamp for the corresponding messages and calculates an offset.
+ *   4. The offset is used to compensate the receivers local clock.
+ *
+ *   Time synchronization is performed in both directions.
+ */
+
+/*******************
+ * Tasks Scheduler *
+ *******************/
+
+// Macros
+#define N_ELEM(x) (sizeof(x) / sizeof((x)[0]))
+
+// Task entry
+typedef struct {
+       void (*task)(uint64_t, uint64_t);
+       uint64_t period;
+       uint64_t due;
+} task_t;
+
+// Task functions
+void task_serial(uint64_t local, uint64_t world);
+void task_events(uint64_t local, uint64_t world);
+void task_sync(uint64_t local, uint64_t world);
+void task_leds(uint64_t local, uint64_t world);
+void task_emit(uint64_t local, uint64_t world);
+void task_debug(uint64_t local, uint64_t world);
+
+// Task table
+task_t tasks[] = {
+       { task_serial, 0          }, // always
+       { task_events, 0          }, // always -- testing
+       { task_sync,   0          }, // always
+       { task_emit,   0          }, // always
+       { task_leds,   100000000  }, // 10hz
+       { task_debug,  1000000000 }, // 1hz
+};
+
+/********************
+ * Data definitions *
+ ********************/
+
+// LEDs
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+
+// Message Parsers
+parser_t   parser_dbg;
+parser_t   parser_bbb;
+parser_t   parser_mbed;
+
+// Serial IRQ
+sirq_t    *sirq_dbg;
+sirq_t    *sirq_bbb;
+sirq_t    *sirq_mbed;
+
+// Timer DMA
+tdma_t    *tdma_evt;
+tdma_t    *tdma_rcv;
+tdma_t    *tdma_xmt;
+
+/*********
+ * Tasks *
+ *********/
+
+void task_serial(uint64_t local, uint64_t world)
+{
+       while (sirq_ready(sirq_dbg)) {
+               //sirq_printf("serial recv - dbg\r\n");
+               msg_receive(&parser_dbg,  sirq_getc(sirq_dbg));
+       }
+
+       while (sirq_ready(sirq_bbb)) {
+               //sirq_printf("serial recv - bbb\r\n");
+               msg_receive(&parser_bbb,  sirq_getc(sirq_bbb));
+       }
+
+       while (sirq_ready(sirq_mbed)) {
+               //sirq_printf("serial recv - mbed\r\n");
+               msg_receive(&parser_mbed, sirq_getc(sirq_mbed));
+       }
+}
+
+void task_events(uint64_t local, uint64_t world)
+{
+       uint64_t event = 0;
+
+#ifdef VERBOSE
+       if (tdma_stamp(tdma_evt, &event)) {
+               sirq_printf("event received - evt\r\n");
+       if (tdma_stamp(tdma_rcv, &event))
+               sirq_printf("event received - rcv\r\n");
+       if (tdma_stamp(tdma_xmt, &event))
+               sirq_printf("event received - xmt\r\n");
+#endif
+
+       if (tdma_stamp(tdma_evt, &event))
+               comm_send_event(0, event);
+       tdma_stop(tdma_evt, 0);
+       tdma_start(tdma_evt);
+}
+
+void task_sync(uint64_t local, uint64_t world)
+{
+       comm_send_sync(local);
+}
+
+void task_leds(uint64_t local, uint64_t world)
+{
+       static uint32_t which = 0;
+       led1 = (which == 0);
+       led2 = (which == 1);
+       which ^= 1;
+}
+
+void task_emit(uint64_t local, uint64_t world)
+{
+       emit_transmit(local, world);
+}
+
+void task_debug(uint64_t local, uint64_t world)
+{
+       //tdma_debug(tdma_rcv);
+       //tdma_debug(tdma_xmt);
+
+       //sirq_debug(sirq_mbed);
+
+       comm_send_event(1, local);
+
+#ifdef VERBOSE
+       sirq_printf("background - %6u.%02u -> %u.%02u\r\n",
+                       (uint32_t)(local / NSEC_PER_SEC),
+                       (uint32_t)(local % NSEC_PER_SEC / 10000000),
+                       (uint32_t)(world / NSEC_PER_SEC),
+                       (uint32_t)(world % NSEC_PER_SEC / 10000000));
+#endif
+}
+
+/********
+ * Main *
+ ********/
+
+void background(void)
+{
+       // Debugging
+       uint64_t local = tdma_time();
+       uint64_t world = time_to_world(local);
+
+       // Run the scheduler
+       for (unsigned i = 0; i < N_ELEM(tasks); i++) {
+               if (local >= tasks[i].due) {
+                       tasks[i].task(local, world);
+                       tasks[i].due += tasks[i].period;
+               }
+       }
+}
+
+int main(int argc, char **argv)
+{
+       // Open serial ports
+       sirq_dbg   = sirq_open(SIRQ_UART0, USBTX, USBRX, 115200, 0); // to pc
+       sirq_bbb   = sirq_open(SIRQ_UART1, PTE0,  PTE1,  115200, 0); // to bbb
+       sirq_mbed  = sirq_open(SIRQ_UART2, PTD3,  PTD2,  115200, 1); // to mbed
+
+       // Setup timers
+       tdma_evt   = tdma_open(TDMA_CHAN0, 3, PTC9,  PullDown); // async event
+       tdma_rcv   = tdma_open(TDMA_CHAN2, 3, PTD2,  PullUp);   // time sync rcv
+       tdma_xmt   = tdma_open(TDMA_CHAN3, 3, PTD3,  PullUp);   // time sync xmt
+
+       // Setup event generation
+       time_init();
+       emit_init(3, PTE20, PullDown);
+       comm_init(sirq_dbg, sirq_bbb, sirq_mbed,
+                       tdma_rcv, tdma_xmt);
+
+       // Register messages
+       msg_register(&parser_dbg,  MSG_ID_INIT,  (handler_t)comm_handle_init);
+       msg_register(&parser_dbg,  MSG_ID_SYNC,  (handler_t)comm_handle_sync);
+       msg_register(&parser_dbg,  MSG_ID_EVENT, (handler_t)comm_handle_event);
+
+       msg_register(&parser_bbb,  MSG_ID_INIT,  (handler_t)comm_handle_init);
+
+       msg_register(&parser_mbed, MSG_ID_INIT,  (handler_t)comm_handle_init);
+       msg_register(&parser_mbed, MSG_ID_SYNC,  (handler_t)comm_handle_sync);
+       msg_register(&parser_mbed, MSG_ID_EVENT, (handler_t)comm_handle_event);
+
+       // start timers
+       tdma_start(tdma_evt);
+       tdma_start(tdma_rcv);
+       tdma_start(tdma_xmt);
+
+       // Run background loop
+       while (true)
+               background();
+
+       return 0;
+}