]> Pileus Git - ~andy/csm213a-hw/blob - hw2/serial_irq.c
Improve time sync accuracy
[~andy/csm213a-hw] / hw2 / serial_irq.c
1 #include <MKL46Z4.h>\r
2 \r
3 #include <stdint.h>\r
4 #include <stdio.h>\r
5 #include "serial_api.h"\r
6 #include "serial_irq.h"\r
7 #include "timer_dma.h"\r
8 \r
9 /* Defines */\r
10 #define SIRQ_LEN  1024\r
11 \r
12 /* Port structure */\r
13 typedef struct {\r
14         int     rix;\r
15         int     wix;\r
16         uint8_t buf[SIRQ_LEN];\r
17 } queue_t;\r
18 \r
19 struct sirq_t {\r
20         serial_t uart;\r
21         queue_t  xmt;\r
22         queue_t  rcv;\r
23 };\r
24 \r
25 /* Test data */\r
26 extern uint32_t test_xmt_enab;\r
27 extern uint64_t test_xmt_time0;\r
28 extern uint64_t test_xmt_time1;\r
29 \r
30 extern uint32_t test_rcv_enab;\r
31 extern uint64_t test_rcv_time;\r
32 \r
33 /* Port data */\r
34 static sirq_t sirq_ports[SIRQ_NUM_UART];\r
35 \r
36 /* Receive handler */\r
37 void sirq_handler(uint32_t _port, SerialIrq event)\r
38 {\r
39         sirq_t *port = (sirq_t *)_port;\r
40 \r
41         // Handle transmit\r
42         if (event == TxIrq && port->xmt.rix != port->xmt.wix) {\r
43                 int byte = port->xmt.buf[port->xmt.rix];\r
44 \r
45                 uint64_t time0 = tdma_time();\r
46                 serial_putc(&port->uart, byte);\r
47                 uint64_t time1 = tdma_time();\r
48 \r
49                 if (test_xmt_enab) {\r
50                         test_xmt_time0 = time0;\r
51                         test_xmt_time1 = time1;\r
52                         test_xmt_enab  = 0;\r
53                 }\r
54 \r
55                 port->xmt.rix = (port->xmt.rix+1) % SIRQ_LEN;\r
56         } else {\r
57                 serial_irq_set(&port->uart, TxIrq, 0);\r
58         }\r
59 \r
60         // Handle receive\r
61         if (event == RxIrq) {\r
62                 int byte = serial_getc(&port->uart);\r
63                 port->rcv.buf[port->rcv.wix] = byte;\r
64                 port->rcv.wix = (port->rcv.wix+1) % SIRQ_LEN;\r
65         }\r
66 }\r
67 \r
68 /* Open port */\r
69 sirq_t *sirq_open(sirq_uart_t uart, PinName tx, PinName rx, int baud)\r
70 {\r
71         // Allocate port\r
72         sirq_t *port = &sirq_ports[uart];\r
73 \r
74         // Configure port\r
75         serial_init(&port->uart, tx, rx);\r
76         serial_baud(&port->uart, baud);\r
77 \r
78         // Set IRQ handlers\r
79         serial_irq_handler(&port->uart, sirq_handler, (uint32_t)port);\r
80         serial_irq_set(&port->uart, RxIrq, 1);\r
81 \r
82         return port;\r
83 }\r
84 \r
85 /* Write byte to the port */\r
86 void sirq_putc(sirq_t *port, int byte)\r
87 {\r
88         port->xmt.buf[port->xmt.wix] = byte;\r
89         port->xmt.wix = (port->xmt.wix+1) % SIRQ_LEN;\r
90         serial_irq_set(&port->uart, TxIrq, 1);\r
91 }\r
92 \r
93 /* Read byte from the port */\r
94 int sirq_getc(sirq_t *port)\r
95 {\r
96         int byte = 0;\r
97         if (port->rcv.rix != port->rcv.wix) {\r
98                 byte = port->rcv.buf[port->rcv.rix];\r
99                 port->rcv.rix = (port->rcv.rix+1) % SIRQ_LEN;\r
100         }\r
101         return byte;\r
102 }\r
103 \r
104 /* Buffered write */\r
105 void sirq_write(sirq_t *port, void *data, int len)\r
106 {\r
107         uint8_t *bytes = (uint8_t*)data;\r
108         for (int i = 0; i < len; i++)\r
109                 sirq_putc(port, bytes[i]);\r
110 }\r
111 \r
112 /* Check if port is writable */\r
113 int sirq_ready(sirq_t *port)\r
114 {\r
115         return port->rcv.rix != port->rcv.wix;\r
116 }\r
117 \r
118 /* Debug print */\r
119 void sirq_debug(sirq_t *port)\r
120 {\r
121         sirq_printf("xmt  - wix:%03x rix:%03x\r\n", port->xmt.wix, port->xmt.rix);\r
122         sirq_printf("rcv  - wix:%03x rix:%03x\r\n", port->rcv.wix, port->rcv.rix);\r
123         sirq_printf("irq  - ??\r\n");\r
124         sirq_printf("uart - ??\r\n");\r
125 \r
126         // __IO uint8_t BDH;     \r
127         // __IO uint8_t BDL;     \r
128         // __IO uint8_t C1;      \r
129         // __IO uint8_t C2;      \r
130         // __IO uint8_t S1;      \r
131         // __IO uint8_t S2;      \r
132         // __IO uint8_t C3;      \r
133         // __IO uint8_t D;       \r
134         // __IO uint8_t MA1;     \r
135         // __IO uint8_t MA2;     \r
136         // __IO uint8_t C4;      \r
137         // __IO uint8_t C5;      \r
138 }\r
139 \r
140 /* Write ASCII data to the output queue */\r
141 void sirq_vprintf(const char *fmt, va_list ap)\r
142 {\r
143         static char buf[512];\r
144         int len = vsnprintf(buf, sizeof(buf), fmt, ap);\r
145         for (int i = 0; i < len; i++)\r
146                 sirq_putc(&sirq_ports[0], buf[i]);\r
147 }\r
148 \r
149 void sirq_printf(const char *fmt, ...)\r
150 {\r
151         va_list ap;\r
152         va_start(ap, fmt);\r
153         sirq_vprintf(fmt, ap);\r
154         va_end(ap);\r
155 }\r