]> Pileus Git - ~andy/csm213a-hw/blob - hw2/main.cpp
Add serial transmit call
[~andy/csm213a-hw] / hw2 / main.cpp
1 #include "messages.h"
2
3 #include "mbed.h"
4 #include "serial_irq.h"
5 #include "serial_dma.h"
6 #include "timer_dma.h"
7
8 #include "main_time.h"
9 #include "main_emit.h"
10 #include "main_comm.h"
11
12 /**
13  * Mode of operation:
14  *   Devices 1 and 2 synchronize clocks using serial messages.
15  *
16  *   1. Each serial message timestamped using the hardware timer capture
17  *      registers in both the sender and receiver.
18  *   2. The sender transmits the send timestamp during the next time-sync
19  *      message.
20  *   3. The receiver then compares the senders timestamp with it's own
21  *      timestamp for the corresponding messages and calculates an offset.
22  *   4. The offset is used to compensate the receivers local clock.
23  *
24  *   Time synchronization is performed in both directions.
25  */
26
27 /*******************
28  * Tasks Scheduler *
29  *******************/
30
31 // Macros
32 #define N_ELEM(x) (sizeof(x) / sizeof((x)[0]))
33
34 // Task entry
35 typedef struct {
36         void (*task)(uint64_t, uint64_t);
37         uint64_t period;
38         uint64_t due;
39 } task_t;
40
41 // Task functions
42 void task_serial(uint64_t local, uint64_t world);
43 void task_events(uint64_t local, uint64_t world);
44 void task_sync(uint64_t local, uint64_t world);
45 void task_leds(uint64_t local, uint64_t world);
46 void task_emit(uint64_t local, uint64_t world);
47 void task_debug(uint64_t local, uint64_t world);
48
49 // Task table
50 task_t tasks[] = {
51         { task_serial, 0          }, // always
52         { task_events, 0          }, // always -- testing
53         { task_sync,   0          }, // always
54         { task_emit,   0          }, // always
55         { task_leds,   100000000  }, // 10hz
56         { task_debug,  1000000000 }, // 1hz
57 };
58
59 /********************
60  * Data definitions *
61  ********************/
62
63 // LEDs
64 DigitalOut led1(LED1);
65 DigitalOut led2(LED2);
66
67 // Message Parsers
68 parser_t   parser_dbg;
69 parser_t   parser_bbb;
70 parser_t   parser_mbed;
71
72 // Serial IRQ
73 sirq_t    *sirq_dbg;
74 sirq_t    *sirq_bbb;
75 sirq_t    *sirq_mbed;
76
77 // Timer DMA
78 tdma_t    *tdma_evt;
79 tdma_t    *tdma_rcv;
80 tdma_t    *tdma_xmt;
81
82 /*********
83  * Tasks *
84  *********/
85
86 void task_serial(uint64_t local, uint64_t world)
87 {
88         while (sirq_ready(sirq_dbg)) {
89                 //sirq_printf("serial recv - dbg\r\n");
90                 msg_receive(&parser_dbg,  sirq_getc(sirq_dbg));
91         }
92
93         while (sirq_ready(sirq_bbb)) {
94                 //sirq_printf("serial recv - bbb\r\n");
95                 msg_receive(&parser_bbb,  sirq_getc(sirq_bbb));
96         }
97
98         while (sirq_ready(sirq_mbed)) {
99                 //sirq_printf("serial recv - mbed\r\n");
100                 msg_receive(&parser_mbed, sirq_getc(sirq_mbed));
101         }
102 }
103
104 void task_events(uint64_t local, uint64_t world)
105 {
106         uint64_t event = 0;
107
108 #ifdef VERBOSE
109         if (tdma_stamp(tdma_evt, &event)) {
110                 sirq_printf("event received - evt\r\n");
111         if (tdma_stamp(tdma_rcv, &event))
112                 sirq_printf("event received - rcv\r\n");
113         if (tdma_stamp(tdma_xmt, &event))
114                 sirq_printf("event received - xmt\r\n");
115 #endif
116
117         if (tdma_stamp(tdma_evt, &event))
118                 comm_send_event(0, event);
119         tdma_stop(tdma_evt, 0);
120         tdma_start(tdma_evt);
121 }
122
123 void task_sync(uint64_t local, uint64_t world)
124 {
125         comm_send_sync(local);
126 }
127
128 void task_leds(uint64_t local, uint64_t world)
129 {
130         static uint32_t which = 0;
131         led1 = (which == 0);
132         led2 = (which == 1);
133         which ^= 1;
134 }
135
136 void task_emit(uint64_t local, uint64_t world)
137 {
138         emit_transmit(local, world);
139 }
140
141 void task_debug(uint64_t local, uint64_t world)
142 {
143         //tdma_debug(tdma_rcv);
144         //tdma_debug(tdma_xmt);
145
146         //sirq_debug(sirq_mbed);
147
148         comm_send_event(1, local);
149
150 #ifdef VERBOSE
151         sirq_printf("background - %6u.%02u -> %u.%02u\r\n",
152                         (uint32_t)(local / NSEC_PER_SEC),
153                         (uint32_t)(local % NSEC_PER_SEC / 10000000),
154                         (uint32_t)(world / NSEC_PER_SEC),
155                         (uint32_t)(world % NSEC_PER_SEC / 10000000));
156 #endif
157 }
158
159 /********
160  * Main *
161  ********/
162
163 void background(void)
164 {
165         // Debugging
166         uint64_t local = tdma_time();
167         uint64_t world = time_to_world(local);
168
169         // Run the scheduler
170         for (unsigned i = 0; i < N_ELEM(tasks); i++) {
171                 if (local >= tasks[i].due) {
172                         tasks[i].task(local, world);
173                         tasks[i].due += tasks[i].period;
174                 }
175         }
176 }
177
178 int main(int argc, char **argv)
179 {
180         // Open serial ports
181         sirq_dbg   = sirq_open(SIRQ_UART0, USBTX, USBRX, 115200, 0); // to pc
182         sirq_bbb   = sirq_open(SIRQ_UART1, PTE0,  PTE1,  115200, 0); // to bbb
183         sirq_mbed  = sirq_open(SIRQ_UART2, PTD3,  PTD2,  115200, 1); // to mbed
184
185         // Setup timers
186         tdma_evt   = tdma_open(TDMA_CHAN0, 3, PTC9,  PullDown); // async event
187         tdma_rcv   = tdma_open(TDMA_CHAN2, 3, PTD2,  PullUp);   // time sync rcv
188         tdma_xmt   = tdma_open(TDMA_CHAN3, 3, PTD3,  PullUp);   // time sync xmt
189
190         // Setup event generation
191         time_init();
192         emit_init(3, PTE20, PullDown);
193         comm_init(sirq_dbg, sirq_bbb, sirq_mbed,
194                         tdma_rcv, tdma_xmt);
195
196         // Register messages
197         msg_register(&parser_dbg,  MSG_ID_INIT,  (handler_t)comm_handle_init);
198         msg_register(&parser_dbg,  MSG_ID_SYNC,  (handler_t)comm_handle_sync);
199         msg_register(&parser_dbg,  MSG_ID_EVENT, (handler_t)comm_handle_event);
200
201         msg_register(&parser_bbb,  MSG_ID_INIT,  (handler_t)comm_handle_init);
202
203         msg_register(&parser_mbed, MSG_ID_SYNC,  (handler_t)comm_handle_sync);
204         msg_register(&parser_mbed, MSG_ID_EVENT, (handler_t)comm_handle_event);
205
206         // start timers
207         tdma_start(tdma_evt);
208         tdma_start(tdma_rcv);
209         tdma_start(tdma_xmt);
210
211         // Run background loop
212         while (true)
213                 background();
214
215         return 0;
216 }