]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Output/uartOut/arm/uart_serial.c
Adding UART and UART + USB muxed CLI output.
[kiibohd-controller.git] / Output / uartOut / arm / uart_serial.c
1 /* Copyright (C) 2014 by Jacob Alexander
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to deal
5  * in the Software without restriction, including without limitation the rights
6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  * copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19  * THE SOFTWARE.
20  */
21
22 #include "uart_serial.h"
23 #include <Lib/OutputLib.h>
24 #include <Lib/Interrupts.h>
25 #include <string.h> // For memcpy
26
27 // ----- Variables -----
28
29 #define uart0_buffer_size 128 // 128 byte buffer
30 volatile uint8_t uart0_buffer_head = 0;
31 volatile uint8_t uart0_buffer_tail = 0;
32 volatile uint8_t uart0_buffer_items = 0;
33 volatile uint8_t uart0_buffer[uart0_buffer_size];
34
35
36 // ----- Interrupt Functions -----
37
38 void uart0_status_isr()
39 {
40         cli(); // Disable Interrupts
41
42         // UART0_S1 must be read for the interrupt to be cleared
43         if ( UART0_S1 & ( UART_S1_RDRF | UART_S1_IDLE ) )
44         {
45                 uint8_t available = UART0_RCFIFO;
46
47                 // If there was actually nothing
48                 if ( available == 0 )
49                 {
50                         // Cleanup
51                         available = UART0_D;
52                         UART0_CFIFO = UART_CFIFO_RXFLUSH;
53                         sei();
54                         return;
55                 }
56
57                 // Read UART0 into buffer until FIFO is empty
58                 while ( available-- > 0 )
59                 {
60                         uart0_buffer[uart0_buffer_tail++] = UART0_D;
61                         uart0_buffer_items++;
62
63                         // Wrap-around of tail pointer
64                         if ( uart0_buffer_tail >= uart0_buffer_size )
65                         {
66                                 uart0_buffer_tail = 0;
67                         }
68
69                         // Make sure the head pointer also moves if circular buffer is overwritten
70                         if ( uart0_buffer_head == uart0_buffer_tail )
71                         {
72                                 uart0_buffer_head++;
73                         }
74
75                         // Wrap-around of head pointer
76                         if ( uart0_buffer_head >= uart0_buffer_size )
77                         {
78                                 uart0_buffer_head = 0;
79                         }
80                 }
81         }
82
83         sei(); // Re-enable Interrupts
84 }
85
86
87 // ----- Functions -----
88
89 void uart_serial_setup()
90 {
91         // Setup the the UART interface for keyboard data input
92         SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating
93
94         // Pin Setup for UART0
95         PORTB_PCR16 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); // RX Pin
96         PORTB_PCR17 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // TX Pin
97
98         // Setup baud rate - 115200 Baud
99         // 48 MHz / ( 16 * Baud ) = BDH/L
100         // Baud: 115200 -> 48 MHz / ( 16 * 115200 ) = 26.0416667
101         // Thus baud setting = 26
102         // NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet
103         uint16_t baud = 26; // Max setting of 8191
104         UART0_BDH = (uint8_t)(baud >> 8);
105         UART0_BDL = (uint8_t)baud;
106         UART0_C4 = 0x02;
107
108         // 8 bit, No Parity, Idle Character bit after stop
109         UART0_C1 = UART_C1_ILT;
110
111         // Interrupt notification watermark
112         UART0_TWFIFO = 2;
113         UART0_RWFIFO = 4;
114
115         // TX FIFO Disabled, TX FIFO Size 1 (Max 8 datawords), RX FIFO Enabled, RX FIFO Size 1 (Max 8 datawords)
116         // TX/RX FIFO Size:
117         //  0x0 - 1 dataword
118         //  0x1 - 4 dataword
119         //  0x2 - 8 dataword
120         UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
121
122         // Reciever Inversion Disabled, LSBF
123         // UART_S2_RXINV UART_S2_MSBF
124         UART0_S2 |= 0x00;
125
126         // Transmit Inversion Disabled
127         // UART_C3_TXINV
128         UART0_C3 |= 0x00;
129
130         // TX Enabled, RX Enabled, RX Interrupt Enabled, Generate idles
131         // UART_C2_TE UART_C2_RE UART_C2_RIE UART_C2_ILIE
132         UART0_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE | UART_C2_ILIE;
133
134         // Add interrupt to the vector table
135         NVIC_ENABLE_IRQ( IRQ_UART0_STATUS );
136 }
137
138
139 // Get the next character, or -1 if nothing received
140 int uart_serial_getchar()
141 {
142         unsigned int value = -1;
143
144         // Check to see if the FIFO has characters
145         if ( uart0_buffer_items > 0 )
146         {
147                 value = uart0_buffer[uart0_buffer_head++];
148                 uart0_buffer_items--;
149
150                 // Wrap-around of head pointer
151                 if ( uart0_buffer_head >= uart0_buffer_size )
152                 {
153                         uart0_buffer_head = 0;
154                 }
155         }
156
157         return value;
158 }
159
160
161 // Number of bytes available in the receive buffer
162 int uart_serial_available()
163 {
164         return uart0_buffer_items;
165 }
166
167
168 // Discard any buffered input
169 void uart_serial_flush_input()
170 {
171         uart0_buffer_head = 0;
172         uart0_buffer_tail = 0;
173         uart0_buffer_items = 0;
174 }
175
176
177 // Transmit a character.  0 returned on success, -1 on error
178 int uart_serial_putchar( uint8_t c )
179 {
180         while ( !( UART0_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
181         UART0_D = c;
182
183         return 0;
184 }
185
186
187 int uart_serial_write( const void *buffer, uint32_t size )
188 {
189         const uint8_t *data = (const uint8_t *)buffer;
190         uint32_t position = 0;
191
192         // While buffer is not empty and transmit buffer is
193         while ( position < size )
194         {
195                 while ( !( UART0_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
196                 UART0_D = data[position++];
197         }
198
199         return 0;
200 }
201
202
203 void uart_serial_flush_output()
204 {
205         // Delay until buffer has been sent
206         while ( !( UART0_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
207 }
208
209
210 void uart_device_reload()
211 {
212         asm volatile("bkpt");
213 }
214