]> Pileus Git - ~andy/csm213a-hw/blobdiff - hw2/main.cpp
Factor out message parser
[~andy/csm213a-hw] / hw2 / main.cpp
index 52e84aa7b242cfbe45a3a7b1c1ce7042ab28f4ed..1bc0cda280da2e3effc2cfe5ab90a815989024fa 100644 (file)
@@ -40,6 +40,12 @@ uint64_t time_to_world(uint64_t local)
        return time_last_world + elapsed;
 }
 
+uint64_t time_to_local(uint64_t world)
+{
+       uint64_t elapsed = world - time_last_world;
+       return time_last_local + elapsed;
+}
+
 /**
  * Synchronize the timer internal state with updates
  * from an external time sync message.
@@ -111,8 +117,36 @@ void time_printf(const char *label, uint64_t local)
  * Signal generation *
  *********************/
 
-#define EMIT_CLOCKS(nsec) ((uint16_t)((nsec) * 24 / 1000))
-#define EMIT_NSEC(clocks) ((uint16_t)((clocks) * 1000 / 24))
+// for 50 Mhz clock  50/1000 = 1/20  (PLL/2)
+
+// for 48 Mhz clock  48/1000 = 6/125 (FLL)
+// for 24 Mhz clock, 24/1000 = 3/125
+// for 12 Mhz clock, 12/1000 = 3/250
+// for  6 Mhz clock,  6/1000 = 3/500
+// for  3 Mhz clock,  3/1000 = 3/1000
+
+#define EMIT_PS 1
+
+//#if EMIT_PS == 0
+//#define EMIT_CLOCKS(nsec) ((uint16_t)((nsec)   / 20))
+//#define EMIT_NSEC(clocks) ((uint16_t)((clocks) * 20))
+
+#if EMIT_PS == 0
+#define EMIT_CLOCKS(nsec) ((uint32_t)((nsec)   * 6 / 125))
+#define EMIT_NSEC(clocks) ((uint32_t)((clocks) * 125 / 6))
+#elif EMIT_PS == 1
+#define EMIT_CLOCKS(nsec) ((uint32_t)((nsec)   * 3 / 125))
+#define EMIT_NSEC(clocks) ((uint32_t)((clocks) * 125 / 3))
+#elif EMIT_PS == 2
+#define EMIT_CLOCKS(nsec) ((uint32_t)((nsec)   * 3 / 250))
+#define EMIT_NSEC(clocks) ((uint32_t)((clocks) * 250 / 3))
+#elif EMIT_PS == 3
+#define EMIT_CLOCKS(nsec) ((uint32_t)((nsec)   * 3 / 500))
+#define EMIT_NSEC(clocks) ((uint32_t)((clocks) * 500 / 3))
+#elif EMIT_PS == 4
+#define EMIT_CLOCKS(nsec) ((uint32_t)((nsec)   * 3 / 1000))
+#define EMIT_NSEC(clocks) ((uint32_t)((clocks) * 1000 / 3))
+#endif
 
 static uint32_t *emit_pcr    = 0; // transmit pin name
 
@@ -132,6 +166,20 @@ void emit_init(int alt, PinName pin, PinMode mode)
        SIM->SCGC6            |= SIM_SCGC6_TPM1_MASK;
        SIM->SOPT2            |= SIM_SOPT2_TPMSRC(1);
 
+       // Reset PLL Source
+       //SIM->SOPT2 &= ~SIM_SOPT2_PLLFLLSEL_MASK;
+
+       // Debug print on SOPT2
+       // -- mbed may set PLLFLL when configuring UART0
+       // SOPT2: u0src=1 tpmsrc=1 USBSRC PLL/2 clkos=0 rtcos
+       sirq_printf("SOPT2: u0src=%d tpmsrc=%d %s %s clkos=%d %s\r\n",
+               (SIM->SOPT2 & SIM_SOPT2_UART0SRC_MASK)     >> SIM_SOPT2_UART0SRC_SHIFT,
+               (SIM->SOPT2 & SIM_SOPT2_TPMSRC_MASK)       >> SIM_SOPT2_TPMSRC_SHIFT,
+               (SIM->SOPT2 & SIM_SOPT2_UART0SRC_MASK)     ? "USBSRC" : "usbsrc",
+               (SIM->SOPT2 & SIM_SOPT2_PLLFLLSEL_MASK)    ? "PLL/2"  : "FLL",
+               (SIM->SOPT2 & SIM_SOPT2_CLKOUTSEL_MASK)    >> SIM_SOPT2_CLKOUTSEL_SHIFT,
+               (SIM->SOPT2 & SIM_SOPT2_RTCCLKOUTSEL_MASK) ? "RTCOS"  : "rtcos");
+
        // Set pin mode
        emit_pcr[0]            = PORT_PCR_ISF_MASK
                               | PORT_PCR_MUX(alt)
@@ -155,15 +203,12 @@ void emit_init(int alt, PinName pin, PinMode mode)
 
 void emit_enable(uint64_t start, uint64_t period)
 {
-       const int slack_clocks = 0x8000; // tune based on emit_worst
+       const int slack_clocks = 0x4000; // tune based on emit_worst
 
        emit_start  = start;
        emit_period = period;
        emit_due    = start + period;
 
-       // TODO - tune slack time
-       // TODO - check clock power
-       // TODO - TPM clock source
        emit_slack  = EMIT_NSEC(slack_clocks);
 
        time_printf("emit scheduled", emit_due);
@@ -171,24 +216,57 @@ void emit_enable(uint64_t start, uint64_t period)
 
 void emit_schedule(uint64_t when)
 {
-       uint64_t now    = time_to_world(tdma_time());
-       uint64_t start  = when - now;     // transmit time
-       uint64_t stop   = start + 100000; // 100 us pulse
+       uint64_t local  = time_to_local(when) * 3 / 125;
+       uint32_t width  = EMIT_CLOCKS(10000);
 
        // Disable timer
        TPM1->SC               = TPM_SC_TOF_MASK;
 
+       __disable_irq();
+
+       uint64_t now    = ((uint64_t)~PIT->LTMR64H << 32)
+                       | ((uint64_t)~PIT->LTMR64L);
+       uint32_t delta  = local - now;
+       uint32_t start  = delta >> (EMIT_PS-1); // convert to clocks
+       uint32_t stop   = start + width;        // end time
+
        // Set transmit time
-       TPM1->CONTROLS[0].CnV  = EMIT_CLOCKS(start);
-       TPM1->MOD              = TPM_MOD_MOD(EMIT_CLOCKS(stop));
+       TPM1->CONTROLS[0].CnV  = start;
+       TPM1->MOD              = TPM_MOD_MOD(stop);
 
        // Start the timer
        TPM1->SC               = TPM_SC_TOF_MASK
-                              | TPM_SC_PS(1)
+                              | TPM_SC_PS(EMIT_PS)
                               | TPM_SC_CMOD(1);
 
+       __enable_irq();
+
+       // Test
+       //int64_t  cnv = TPM1->CONTROLS[0].CnV;
+       //int64_t  mod = TPM1->MOD;
+       //int64_t  due = local - tdma_time();
+       //sirq_printf("%6d -- cnv=%04x mod=%04x due=%04x start=%04x\r\n",
+       //              (int)(cnv - EMIT_CLOCKS(due)),
+       //              (int)cnv, (int)mod,
+       //              (int)EMIT_CLOCKS(due), EMIT_CLOCKS(start));
+
+       // Clock testing
+       //uint32_t test_tpm0 =  TPM1->CNT;
+       //uint32_t test_pit0 = ~PIT->CHANNEL[0].CVAL;
+       //for (int i = 0; i < 100; i++)
+       //      asm("nop");
+       //uint32_t test_tpm1 =  TPM1->CNT;
+       //uint32_t test_pit1 = ~PIT->CHANNEL[0].CVAL;
+
+       //uint32_t test_tpm  = test_tpm1 - test_tpm0;
+       //uint32_t test_pit  = test_pit1 - test_pit0;
+       //sirq_printf("pit/tpm: %d - tpm=%08x/%08x=%d pit=%08x/%08x=%d\r\n",
+       //              test_tpm - test_pit,
+       //              test_tpm0, test_tpm1, test_tpm,
+       //              test_pit0, test_pit1, test_pit);
+
        // Debug output
-       //sirq_printf("emitting event\r\n");
+       //time_printf("emitting event", when);
 }
 
 void emit_transmit(uint64_t local, uint64_t world)
@@ -212,12 +290,6 @@ void emit_transmit(uint64_t local, uint64_t world)
  * Serial I/O functions *
  ************************/
 
-typedef struct {
-       int      index;
-       int      state;
-       uint8_t  buffer[256];
-} parser_t;
-
 static uint32_t serial_device_id   = 0;
 
 const  uint64_t serial_sync_delay  = NSEC_PER_SEC / 100;
@@ -316,7 +388,7 @@ void serial_send_sync(sirq_t *port, uint64_t now)
  */
 void serial_send_event(sirq_t *port, uint16_t event, uint64_t local)
 {
-       time_printf("event received", local);
+       //time_printf("event received", local);
 
        // Convert timestamp
        uint64_t world = time_to_world(local);
@@ -346,7 +418,7 @@ void serial_send_event(sirq_t *port, uint16_t event, uint64_t local)
 /**
  * Handle init message
  */
-void serial_handle_init(init_msg_t *msg)
+void serial_handle_init(int msgid, init_msg_t *msg)
 {
        sirq_printf("initialize: %s %s %s %s %s\r\n",
                msg->valid & MSG_VALID_DEVICE ? "DEV"    : "dev",
@@ -382,7 +454,7 @@ void serial_handle_init(init_msg_t *msg)
 /**
  * Handle sync message
  */
-void serial_handle_sync(sync_msg_t *msg)
+void serial_handle_sync(int msgid, sync_msg_t *msg)
 {
        // Read receive timestamp
        uint64_t local = 0, world = 0;
@@ -409,77 +481,10 @@ void serial_handle_sync(sync_msg_t *msg)
 /**
  * Handle event message
  */
-void serial_handle_event(event_msg_t *msg)
+void serial_handle_event(int msgid, event_msg_t *msg)
 {
 }
 
-/**
- * Deliver message
- */
-void serial_deliver(int msgid, void *body)
-{
-       switch (msgid) {
-               case MSG_ID_INIT:
-                       //sirq_printf("received init msg\r\n");
-                       serial_handle_init((init_msg_t*)body);
-                       break;
-               case MSG_ID_SYNC:
-                       //sirq_printf("received sync msg\r\n");
-                       serial_handle_sync((sync_msg_t*)body);
-                       break;
-               case MSG_ID_EVENT:
-                       //sirq_printf("received event msg\r\n");
-                       serial_handle_event((event_msg_t*)body);
-                       break;
-       }
-}
-
-/**
- * Process serial receive messages
- */
-void serial_receive(parser_t *parser, int byte)
-{
-       //sirq_printf("serial_receive - %02x\r\n", byte);
-
-       // Lookup pointers
-       header_t *head = (header_t*)parser->buffer;
-       void     *body = (void*)(head+1);
-       const int max_length = sizeof(parser->buffer)-sizeof(header_t);
-
-       // Process uart messages
-       parser->buffer[parser->index++] = byte;
-       switch (parser->state) {
-               case 0: // Search
-                       if (parser->index == sizeof(uint16_t)) {
-                               if (head->header == MSG_HEADER) {
-                                       parser->state = 1;
-                               } else {
-                                       parser->buffer[0] = parser->buffer[1];
-                                       parser->index = 1;
-                               }
-                       }
-                       break;
-               case 1: // Header
-                       if (parser->index == sizeof(header_t)) {
-                               if (head->length <= max_length &&
-                                   head->msgid  <= MSG_MAX_ID) {
-                                       parser->state = 2;
-                               } else {
-                                       parser->index = 0;
-                                       parser->state = 0;
-                               }
-                       }
-                       break;
-               case 2: // Data
-                       if (parser->index == (int)sizeof(header_t)+head->length) {
-                               serial_deliver(head->msgid, body);
-                               parser->index = 0;
-                               parser->state = 0;
-                       }
-                       break;
-       }
-}
-
 /********************
  * Data definitions *
  ********************/
@@ -511,17 +516,17 @@ void task_serial(uint64_t local, uint64_t world)
 {
        while (sirq_ready(sirq_dbg)) {
                //sirq_printf("serial recv - dbg\r\n");
-               serial_receive(&parser_dbg,  sirq_getc(sirq_dbg));
+               msg_receive(&parser_dbg,  sirq_getc(sirq_dbg));
        }
 
        while (sirq_ready(sirq_bbb)) {
                //sirq_printf("serial recv - bbb\r\n");
-               serial_receive(&parser_bbb,  sirq_getc(sirq_bbb));
+               msg_receive(&parser_bbb,  sirq_getc(sirq_bbb));
        }
 
        while (sirq_ready(sirq_mbed)) {
                //sirq_printf("serial recv - mbed\r\n");
-               serial_receive(&parser_mbed, sirq_getc(sirq_mbed));
+               msg_receive(&parser_mbed, sirq_getc(sirq_mbed));
        }
 }
 
@@ -620,9 +625,6 @@ void background(void)
 int main(int argc, char **argv)
 {
        tdma_init();
-       emit_init(3, PTE20, PullDown);
-
-       //pin = 1;
 
        // Open serial ports
        sirq_dbg   = sirq_open(SIRQ_UART0, USBTX, USBRX, 115200); // to pc
@@ -631,14 +633,15 @@ int main(int argc, char **argv)
 
        // Setup timers
        tdma_evt   = tdma_open(TDMA_CHAN0, 3, PTC9,  PullDown); // async event
-
-       // mbed time sync
        tdma_rcv   = tdma_open(TDMA_CHAN2, 3, PTD2,  PullUp);   // time sync rcv
        tdma_xmt   = tdma_open(TDMA_CHAN3, 3, PTD3,  PullUp);   // time sync xmt
 
-       // host time sync
-       //tdma_rcv   = tdma_open(TDMA_CHAN2, 2, USBRX, PullUp); // time sync rcv
-       //tdma_xmt   = tdma_open(TDMA_CHAN3, 2, USBTX, PullUp); // time sync xmt
+       // Register messages
+       msg_register(&parser_dbg,  MSG_ID_INIT,  (handler_t)serial_handle_init);
+       msg_register(&parser_dbg,  MSG_ID_SYNC,  (handler_t)serial_handle_sync);
+       msg_register(&parser_dbg,  MSG_ID_EVENT, (handler_t)serial_handle_event);
+       msg_register(&parser_bbb,  MSG_ID_INIT,  (handler_t)serial_handle_init);
+       msg_register(&parser_mbed, MSG_ID_SYNC,  (handler_t)serial_handle_sync);
 
        // start timers
        tdma_start(tdma_evt);
@@ -649,68 +652,13 @@ int main(int argc, char **argv)
        serial_tdma_rcv = tdma_rcv;
        serial_tdma_xmt = tdma_xmt;
 
-       // Test clocks
-       //MCG->C1    = 0x05; // was 0x1A
-       //MCG->C2    = 0x2C; // was 0x24
-       //MCG->C3    = 0x91; // was 0x91
-       //MCG->C4    = 0x10; // was 0x10
-       //MCG->C5    = 0x01; // was 0x01
-       //MCG->C6    = 0x40; // was 0x40
-       //MCG->S     = 0x6E; // was 0x6E
-       //MCG->SC    = 0x02; // was 0x02
-       //MCG->ATCVH = 0x00; // was 0x00
-       //MCG->ATCVL = 0x00; // was 0x00
-       //MCG->C7    = 0x00; // was 0x00
-       //MCG->C8    = 0x80; // was 0x80
-       //MCG->C9    = 0x00; // was 0x00
-       //MCG->C10   = 0x00; // was 0x00
-
-       //sirq_printf("MGC - C1    %02hx\r\n", MCG->C1);     // 1A
-       //sirq_printf("MGC - C2    %02hx\r\n", MCG->C2);     // 24
-       //sirq_printf("MGC - C3    %02hx\r\n", MCG->C3);     // 91
-       //sirq_printf("MGC - C4    %02hx\r\n", MCG->C4);     // 10
-       //sirq_printf("MGC - C5    %02hx\r\n", MCG->C5);     // 01
-       //sirq_printf("MGC - C6    %02hx\r\n", MCG->C6);     // 40
-       //sirq_printf("MGC - S     %02hx\r\n", MCG->S);      // 6E
-       //sirq_printf("MGC - SC    %02hx\r\n", MCG->SC);     // 02
-       //sirq_printf("MGC - ATCVH %02hx\r\n", MCG->ATCVH);  // 00
-       //sirq_printf("MGC - ATCVL %02hx\r\n", MCG->ATCVL);  // 00
-       //sirq_printf("MGC - C7    %02hx\r\n", MCG->C7);     // 00
-       //sirq_printf("MGC - C8    %02hx\r\n", MCG->C8);     // 80
-       //sirq_printf("MGC - C9    %02hx\r\n", MCG->C9);     // 00
-       //sirq_printf("MGC - C10   %02hx\r\n", MCG->C10);    // 00
+       // Setup event generation
+       emit_init(3, PTE20, PullDown);
 
        // Run background loop
        while (true)
                background();
 
-       // Performance testing
-       //uint64_t prev = 0, due = 0;
-       //uint64_t worst[10] = {};
-       //int      count = 0;
-       //while (true) {
-       //      uint64_t local = tdma_time();
-       //      if (prev && (local-prev) > worst[count])
-       //              worst[count] = (local-prev);
-       //      prev = local;
-       //      if (local > due) {
-       //              if (count == 5) {
-       //                      static char str[] = "background background background\r\n";
-       //                      sirq_write(sirq_dbg, str, sizeof(str));
-       //              }
-       //              if (count == 9) {
-       //                      sirq_printf("background\r\n");
-       //                      for (int i = 0; i < 10; i++) {
-       //                              sirq_printf("  worst[%d] = 0.%09u\r\n",
-       //                                              i, worst[i]);
-       //                              worst[i] = 0;
-       //                      }
-       //              }
-       //              due += NSEC_PER_SEC;
-       //              count = (count + 1) % 10;
-       //      }
-       //}
-
        // Run tests
        //test_main();