]> git.donarmstrong.com Git - kiibohd-controller.git/blob - Output/uartOut/arm/uart_serial.c
Initial code for ARM UART output module (mainly for CLI)
[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 32 // 32 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 )
44         {
45                 // Read UART0 into buffer until FIFO is empty
46                 while ( !( UART0_SFIFO & UART_SFIFO_RXEMPT ) )
47                 {
48                         uart0_buffer[uart0_buffer_tail++] = UART0_D;
49                         uart0_buffer_items++;
50
51                         // Wrap-around of tail pointer
52                         if ( uart0_buffer_tail >= uart0_buffer_size )
53                         {
54                                 uart0_buffer_tail = 0;
55                         }
56
57                         // Make sure the head pointer also moves if circular buffer is overwritten
58                         if ( uart0_buffer_head == uart0_buffer_tail )
59                         {
60                                 uart0_buffer_head++;
61                         }
62
63                         // Wrap-around of head pointer
64                         if ( uart0_buffer_head >= uart0_buffer_size )
65                         {
66                                 uart0_buffer_head = 0;
67                         }
68
69                 }
70         }
71
72         sei(); // Re-enable Interrupts
73 }
74
75
76 // ----- Functions -----
77
78 void uart_serial_setup()
79 {
80         // Setup the the UART interface for keyboard data input
81         SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating
82
83         // Pin Setup for UART0
84         PORTB_PCR16 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); // RX Pin
85         PORTB_PCR17 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // TX Pin
86
87         // Setup baud rate - 9600 Baud
88         // 48 MHz / ( 16 * Baud ) = BDH/L
89         // Baud: 9600 -> 48 MHz / ( 16 * 9600 ) = 312.5
90         // Thus baud setting = 313
91         // NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet
92         uint16_t baud = 313; // Max setting of 8191
93         UART0_BDH = (uint8_t)(baud >> 8);
94         UART0_BDL = (uint8_t)baud;
95
96         // 8 bit, No Parity, Idle Character bit after stop
97         UART0_C1 = UART_C1_ILT;
98
99         // TX FIFO Disabled, TX FIFO Size 1 (Max 8 datawords), RX FIFO Enabled, RX FIFO Size 1 (Max 8 datawords)
100         // TX/RX FIFO Size:
101         //  0x0 - 1 dataword
102         //  0x1 - 4 dataword
103         //  0x2 - 8 dataword
104         UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
105
106         // Reciever Inversion Disabled, LSBF
107         // UART_S2_RXINV UART_S2_MSBF
108         UART0_S2 |= 0x00;
109
110         // Transmit Inversion Disabled
111         // UART_C3_TXINV
112         UART0_C3 |= 0x00;
113
114         // TX Disabled, RX Enabled, RX Interrupt Enabled
115         // UART_C2_TE UART_C2_RE UART_C2_RIE
116         UART0_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE;
117
118         // Add interrupt to the vector table
119         NVIC_ENABLE_IRQ( IRQ_UART0_STATUS );
120 }
121
122
123 // Get the next character, or -1 if nothing received
124 int uart_serial_getchar()
125 {
126         unsigned int value = -1;
127
128         // Check to see if the FIFO has characters
129         if ( uart0_buffer_items > 0 )
130         {
131                 value = uart0_buffer[uart0_buffer_head++];
132                 uart0_buffer_items--;
133
134                 // Wrap-around of head pointer
135                 if ( uart0_buffer_head >= uart0_buffer_size )
136                 {
137                         uart0_buffer_head = 0;
138                 }
139         }
140
141         return value;
142 }
143
144
145 // Number of bytes available in the receive buffer
146 int uart_serial_available()
147 {
148         return uart0_buffer_items;
149 }
150
151
152 // Discard any buffered input
153 void uart_serial_flush_input()
154 {
155         uart0_buffer_head = 0;
156         uart0_buffer_tail = 0;
157         uart0_buffer_items = 0;
158 }
159
160
161 // Transmit a character.  0 returned on success, -1 on error
162 int uart_serial_putchar( uint8_t c )
163 {
164         return uart_serial_write( &c, 1 );
165 }
166
167
168 int uart_serial_write( const void *buffer, uint32_t size )
169 {
170         const uint8_t *data = (const uint8_t *)buffer;
171         uint32_t position = 0;
172
173         // While buffer is not empty and transmit buffer is
174         while ( position < size )
175         {
176                 while ( !( UART0_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
177                 UART0_D = data[position++];
178         }
179
180         return 0;
181 }
182
183
184 void uart_serial_flush_output()
185 {
186         // Delay until buffer has been sent
187         while ( !( UART0_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
188 }
189
190
191 void uart_device_reload()
192 {
193         asm volatile("bkpt");
194 }
195