]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Output/uartOut/arm/uart_serial.c
McHCK now working with UART.
[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 volatile uint8_t uart_configured = 0;
36
37
38
39 // ----- Interrupt Functions -----
40
41 void uart0_status_isr()
42 {
43         cli(); // Disable Interrupts
44
45         // UART0_S1 must be read for the interrupt to be cleared
46         if ( UART0_S1 & ( UART_S1_RDRF | UART_S1_IDLE ) )
47         {
48                 uint8_t available = UART0_RCFIFO;
49
50                 // If there was actually nothing
51                 if ( available == 0 )
52                 {
53                         // Cleanup
54                         available = UART0_D;
55                         UART0_CFIFO = UART_CFIFO_RXFLUSH;
56                         sei();
57                         return;
58                 }
59
60                 // Read UART0 into buffer until FIFO is empty
61                 while ( available-- > 0 )
62                 {
63                         uart0_buffer[uart0_buffer_tail++] = UART0_D;
64                         uart0_buffer_items++;
65
66                         // Wrap-around of tail pointer
67                         if ( uart0_buffer_tail >= uart0_buffer_size )
68                         {
69                                 uart0_buffer_tail = 0;
70                         }
71
72                         // Make sure the head pointer also moves if circular buffer is overwritten
73                         if ( uart0_buffer_head == uart0_buffer_tail )
74                         {
75                                 uart0_buffer_head++;
76                         }
77
78                         // Wrap-around of head pointer
79                         if ( uart0_buffer_head >= uart0_buffer_size )
80                         {
81                                 uart0_buffer_head = 0;
82                         }
83                 }
84         }
85
86         sei(); // Re-enable Interrupts
87 }
88
89
90
91 // ----- Functions -----
92
93 void uart_serial_setup()
94 {
95         // Indication that the UART is not ready yet
96         uart_configured = 0;
97
98         // Setup the the UART interface for keyboard data input
99         SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating
100
101 // MCHCK
102 #if defined(_mk20dx128vlf5_)
103         // Pin Setup for UART0
104         PORTA_PCR1 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(2); // RX Pin
105         PORTA_PCR2 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2); // TX Pin
106
107 // Teensy
108 #else
109         // Pin Setup for UART0
110         PORTB_PCR16 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); // RX Pin
111         PORTB_PCR17 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // TX Pin
112 #endif
113
114         // Setup baud rate - 115200 Baud
115         // 48 MHz / ( 16 * Baud ) = BDH/L
116         // Baud: 115200 -> 48 MHz / ( 16 * 115200 ) = 26.0416667
117         // Thus baud setting = 26
118         // NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet
119         uint16_t baud = 26; // Max setting of 8191
120         UART0_BDH = (uint8_t)(baud >> 8);
121         UART0_BDL = (uint8_t)baud;
122         UART0_C4 = 0x02;
123
124         // 8 bit, No Parity, Idle Character bit after stop
125         UART0_C1 = UART_C1_ILT;
126
127         // Interrupt notification watermarks
128         UART0_TWFIFO = 2;
129         UART0_RWFIFO = 4;
130
131         // TX FIFO Disabled, TX FIFO Size 1 (Max 8 datawords), RX FIFO Enabled, RX FIFO Size 1 (Max 8 datawords)
132         // TX/RX FIFO Size:
133         //  0x0 - 1 dataword
134         //  0x1 - 4 dataword
135         //  0x2 - 8 dataword
136         UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
137
138         // Reciever Inversion Disabled, LSBF
139         // UART_S2_RXINV UART_S2_MSBF
140         UART0_S2 |= 0x00;
141
142         // Transmit Inversion Disabled
143         // UART_C3_TXINV
144         UART0_C3 |= 0x00;
145
146         // TX Enabled, RX Enabled, RX Interrupt Enabled, Generate idles
147         // UART_C2_TE UART_C2_RE UART_C2_RIE UART_C2_ILIE
148         UART0_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE | UART_C2_ILIE;
149
150         // Add interrupt to the vector table
151         NVIC_ENABLE_IRQ( IRQ_UART0_STATUS );
152
153         // UART is now ready to use
154         uart_configured = 1;
155 }
156
157
158 // Get the next character, or -1 if nothing received
159 int uart_serial_getchar()
160 {
161         if ( !uart_configured )
162                 return -1;
163
164         unsigned int value = -1;
165
166         // Check to see if the FIFO has characters
167         if ( uart0_buffer_items > 0 )
168         {
169                 value = uart0_buffer[uart0_buffer_head++];
170                 uart0_buffer_items--;
171
172                 // Wrap-around of head pointer
173                 if ( uart0_buffer_head >= uart0_buffer_size )
174                 {
175                         uart0_buffer_head = 0;
176                 }
177         }
178
179         return value;
180 }
181
182
183 // Number of bytes available in the receive buffer
184 int uart_serial_available()
185 {
186         return uart0_buffer_items;
187 }
188
189
190 // Discard any buffered input
191 void uart_serial_flush_input()
192 {
193         uart0_buffer_head = 0;
194         uart0_buffer_tail = 0;
195         uart0_buffer_items = 0;
196 }
197
198
199 // Transmit a character.  0 returned on success, -1 on error
200 int uart_serial_putchar( uint8_t c )
201 {
202         if ( !uart_configured )
203                 return -1;
204
205         while ( !( UART0_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
206         UART0_D = c;
207
208         return 0;
209 }
210
211
212 int uart_serial_write( const void *buffer, uint32_t size )
213 {
214         if ( !uart_configured )
215                 return -1;
216
217         const uint8_t *data = (const uint8_t *)buffer;
218         uint32_t position = 0;
219
220         // While buffer is not empty and transmit buffer is
221         while ( position < size )
222         {
223                 while ( !( UART0_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
224                 UART0_D = data[position++];
225         }
226
227         return 0;
228 }
229
230
231 void uart_serial_flush_output()
232 {
233         // Delay until buffer has been sent
234         while ( !( UART0_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
235 }
236
237
238 void uart_device_reload()
239 {
240         asm volatile("bkpt");
241 }
242