]> Pileus Git - ~andy/csm213a-hw/blob - hw2/serial_irq.c
67beeab353ff9ac707eb13696a678925f41443e9
[~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 \r
8 /* Defines */\r
9 #define SIRQ_LEN  1024\r
10 \r
11 /* Port structure */\r
12 typedef struct {\r
13         int     rix;\r
14         int     wix;\r
15         uint8_t buf[SIRQ_LEN];\r
16 } queue_t;\r
17 \r
18 struct sirq_t {\r
19         serial_t uart;\r
20         queue_t  xmt;\r
21         queue_t  rcv;\r
22 };\r
23 \r
24 /* Port data */\r
25 static sirq_t sirq_ports[SIRQ_NUM_UART];\r
26 \r
27 /* Receive handler */\r
28 void sirq_handler(uint32_t _port, SerialIrq event)\r
29 {\r
30         sirq_t *port = (sirq_t *)_port;\r
31 \r
32         // Handle transmit\r
33         if (event == TxIrq && port->xmt.rix != port->xmt.wix) {\r
34                 int byte = port->xmt.buf[port->xmt.rix];\r
35                 serial_putc(&port->uart, byte);\r
36                 port->xmt.rix = (port->xmt.rix+1) % SIRQ_LEN;\r
37         } else {\r
38                 serial_irq_set(&port->uart, TxIrq, 0);\r
39         }\r
40 \r
41         // Handle receive\r
42         if (event == RxIrq) {\r
43                 int byte = serial_getc(&port->uart);\r
44                 port->rcv.buf[port->rcv.wix] = byte;\r
45                 port->rcv.wix = (port->rcv.wix+1) % SIRQ_LEN;\r
46         }\r
47 }\r
48 \r
49 /* Open port */\r
50 sirq_t *sirq_open(sirq_uart_t uart, PinName tx, PinName rx, int baud)\r
51 {\r
52         // Allocate port\r
53         sirq_t *port = &sirq_ports[uart];\r
54 \r
55         // Configure port\r
56         serial_init(&port->uart, tx, rx);\r
57         serial_baud(&port->uart, baud);\r
58 \r
59         // Set IRQ handlers\r
60         serial_irq_handler(&port->uart, sirq_handler, (uint32_t)port);\r
61         serial_irq_set(&port->uart, RxIrq, 1);\r
62 \r
63         return port;\r
64 }\r
65 \r
66 /* Write byte to the port */\r
67 void sirq_putc(sirq_t *port, int byte)\r
68 {\r
69         port->xmt.buf[port->xmt.wix] = byte;\r
70         port->xmt.wix = (port->xmt.wix+1) % SIRQ_LEN;\r
71         serial_irq_set(&port->uart, TxIrq, 1);\r
72 }\r
73 \r
74 /* Read byte from the port */\r
75 int sirq_getc(sirq_t *port)\r
76 {\r
77         int byte = 0;\r
78         if (port->rcv.rix < port->rcv.wix) {\r
79                 byte = port->rcv.buf[port->rcv.rix];\r
80                 port->rcv.rix = (port->rcv.rix+1) % SIRQ_LEN;\r
81         }\r
82         return byte;\r
83 }\r
84 \r
85 /* Buffered write */\r
86 void sirq_write(sirq_t *port, void *data, int len)\r
87 {\r
88         uint8_t *bytes = (uint8_t*)data;\r
89         for (int i = 0; i < len; i++)\r
90                 sirq_putc(port, bytes[i]);\r
91 }\r
92 \r
93 /* Check if port is writable */\r
94 int sirq_ready(sirq_t *port)\r
95 {\r
96         return port->rcv.rix < port->rcv.wix;\r
97 }\r
98 \r
99 /* Write ASCII data to the output queue */\r
100 void sirq_vprintf(const char *fmt, va_list ap)\r
101 {\r
102         static char buf[512];\r
103         int len = vsnprintf(buf, sizeof(buf), fmt, ap);\r
104         for (int i = 0; i < len; i++)\r
105                 sirq_putc(&sirq_ports[0], buf[i]);\r
106 }\r
107 \r
108 void sirq_printf(const char *fmt, ...)\r
109 {\r
110         va_list ap;\r
111         va_start(ap, fmt);\r
112         sirq_vprintf(fmt, ap);\r
113         va_end(ap);\r
114 }\r