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