]> Pileus Git - ~andy/csm213a-hw/blob - hw2/serial_irq.c
e002ce94f49a07c96d7436612ab4cbaa014bc214
[~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         int      irq;\r
24 };\r
25 \r
26 /* Port data */\r
27 static sirq_t sirq_ports[SIRQ_NUM_UART];\r
28 \r
29 /* Receive handler */\r
30 void sirq_handler(uint32_t _port, SerialIrq event)\r
31 {\r
32         sirq_t *port = (sirq_t *)_port;\r
33 \r
34         // Handle transmit\r
35         if (event == TxIrq && port->xmt.rix != port->xmt.wix) {\r
36                 int byte = port->xmt.buf[port->xmt.rix];\r
37                 serial_putc(&port->uart, byte);\r
38                 port->xmt.rix = (port->xmt.rix+1) % SIRQ_LEN;\r
39         } else {\r
40                 serial_irq_set(&port->uart, TxIrq, 0);\r
41                 port->irq = 0;\r
42         }\r
43 \r
44         // Handle receive\r
45         if (event == RxIrq) {\r
46                 int byte = serial_getc(&port->uart);\r
47                 port->rcv.buf[port->rcv.wix] = byte;\r
48                 port->rcv.wix = (port->rcv.wix+1) % SIRQ_LEN;\r
49         }\r
50 }\r
51 \r
52 /* Open port */\r
53 sirq_t *sirq_open(sirq_uart_t uart, PinName tx, PinName rx, int baud)\r
54 {\r
55         // Allocate port\r
56         sirq_t *port = &sirq_ports[uart];\r
57 \r
58         // Configure port\r
59         serial_init(&port->uart, tx, rx);\r
60         serial_baud(&port->uart, baud);\r
61 \r
62         // Set IRQ handlers\r
63         serial_irq_handler(&port->uart, sirq_handler, (uint32_t)port);\r
64         serial_irq_set(&port->uart, RxIrq, 1);\r
65 \r
66         return port;\r
67 }\r
68 \r
69 /* Write byte to the port */\r
70 void sirq_putc(sirq_t *port, int byte)\r
71 {\r
72         port->xmt.buf[port->xmt.wix] = byte;\r
73         port->xmt.wix = (port->xmt.wix+1) % SIRQ_LEN;\r
74         if (!port->irq) {\r
75                 port->irq = 1;\r
76                 serial_irq_set(&port->uart, TxIrq, 1);\r
77         }\r
78 }\r
79 \r
80 /* Read byte from the port */\r
81 int sirq_getc(sirq_t *port)\r
82 {\r
83         int byte = 0;\r
84         if (port->rcv.rix != port->rcv.wix) {\r
85                 byte = port->rcv.buf[port->rcv.rix];\r
86                 port->rcv.rix = (port->rcv.rix+1) % SIRQ_LEN;\r
87         }\r
88         return byte;\r
89 }\r
90 \r
91 /* Buffered write */\r
92 void sirq_write(sirq_t *port, void *data, int len)\r
93 {\r
94         uint8_t *bytes = (uint8_t*)data;\r
95         for (int i = 0; i < len; i++)\r
96                 sirq_putc(port, bytes[i]);\r
97 }\r
98 \r
99 /* Check if port is writable */\r
100 int sirq_ready(sirq_t *port)\r
101 {\r
102         return port->rcv.rix != port->rcv.wix;\r
103 }\r
104 \r
105 /* Debug print */\r
106 void sirq_debug(sirq_t *port)\r
107 {\r
108         sirq_printf("xmt  - wix:%03x rix:%03x\r\n", port->xmt.wix, port->xmt.rix);\r
109         sirq_printf("rcv  - wix:%03x rix:%03x\r\n", port->rcv.wix, port->rcv.rix);\r
110         sirq_printf("irq  - ??\r\n");\r
111         sirq_printf("uart - ??\r\n");\r
112 \r
113         // __IO uint8_t BDH;     \r
114         // __IO uint8_t BDL;     \r
115         // __IO uint8_t C1;      \r
116         // __IO uint8_t C2;      \r
117         // __IO uint8_t S1;      \r
118         // __IO uint8_t S2;      \r
119         // __IO uint8_t C3;      \r
120         // __IO uint8_t D;       \r
121         // __IO uint8_t MA1;     \r
122         // __IO uint8_t MA2;     \r
123         // __IO uint8_t C4;      \r
124         // __IO uint8_t C5;      \r
125 }\r
126 \r
127 /* Write ASCII data to the output queue */\r
128 void sirq_vprintf(const char *fmt, va_list ap)\r
129 {\r
130         static char buf[512];\r
131         int len = vsnprintf(buf, sizeof(buf), fmt, ap);\r
132         for (int i = 0; i < len; i++)\r
133                 sirq_putc(&sirq_ports[0], buf[i]);\r
134 }\r
135 \r
136 void sirq_printf(const char *fmt, ...)\r
137 {\r
138         va_list ap;\r
139         va_start(ap, fmt);\r
140         sirq_vprintf(fmt, ap);\r
141         va_end(ap);\r
142 }\r