OSDN Git Service

[v2.0] Start to add UART terminal.
[openi2cradio/OpenI2CRadio.git] / euart.c
1 /*
2  * OpenI2CRADIO
3  * EUSART Handler
4  * Copyright (C) 2013-06-20 K.Ohta <whatisthis.sowhat ai gmail.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2,
9  *  or (at your option) any later version.
10  *  This library / program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  *  See the GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this library; see the file COPYING. If not, write to the
17  *  Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
18  *  MA 02110-1301, USA.
19  *
20  *  As a special exception, if you link this(includeed from sdcc) library
21  *  with other files, some of which are compiled with SDCC,
22  *  to produce an executable, this library does not by itself cause
23  *  the resulting executable to be covered by the GNU General Public License.
24  *  This exception does not however invalidate any other reasons why
25  *  the executable file might be covered by the GNU General Public License.
26  */
27
28 #if defined(__SDCC)
29 #include <sdcc-lib.h>
30 #include <pic18fregs.h> /* ONLY FOR PIC18x */
31 #include <delay.h>
32 #else
33 #include <xc.h>
34 #endif
35 #include <signal.h>
36
37 #include "iodef.h"
38 #include "idle.h"
39 #include "ioports.h"
40 #include "euart.h"
41
42 static char uart_rfifo[UART_BUF_SIZE];
43
44 static unsigned int uart_rx_rptr;
45 static unsigned int uart_rx_wptr;
46 static int uart_rx_bytes;
47 static unsigned char uart_rx_sts;
48 static unsigned char uart_rx_xon;
49 static unsigned char uart_tx_xon;
50
51 static unsigned char uart_rx_wakeup;
52
53 void uart_sleep(void)
54 {
55     PIR1bits.TX1IF = 0;
56     PIR1bits.RC1IF = 0;
57     IPR1bits.TX1IP = 0;  // Low
58     IPR1bits.RC1IP = 1; // High
59     RCSTA = 0b00010000; //SPEN, 8bit, ASYNC, CREN
60     BAUDCON = 0b00001011; // IDLE High, BRG16, ABDEN, WUE
61     TXSTA = 0b00100000; //8bit, ASYNC, TXEN, Break
62     PIE1bits.TX1IE = 0;
63     PIE1bits.RC1IE = 0;
64     uart_rx_wakeup = 0;
65 }
66
67 void uart_wakeup(void)
68 {
69     PIR1bits.TX1IF = 0;
70     PIR1bits.RC1IF = 0;
71     IPR1bits.TX1IP = 0;  // Low
72     IPR1bits.RC1IP = 1; // High
73     RCSTA = 0b10010000; //SPEN, 8bit, ASYNC, CREN
74     BAUDCON = 0b00001011; // IDLE High, BRG16, ABDEN, WUE
75     TXSTA = 0b00100000; //8bit, ASYNC, TXEN, Break
76     PIE1bits.TX1IE = 0;
77     PIE1bits.RC1IE = 1;
78 }
79
80 void uart_init(void)
81 {
82     uart_rx_rptr = 0;
83     uart_rx_wptr = 0;
84     uart_rx_bytes = 0;
85     uart_rx_wakeup = 0;
86     uart_rx_xon = 0xff;
87     uart_tx_xon = 0xff;
88     uart_wakeup();
89 }
90
91
92 void uart_inthdr_rx(void)
93 {
94     unsigned char c;
95
96     if(uart_rx_wakeup == 0){
97         if(BAUDCONbits.WUE != 1){ // Okay, Wakeup interrupt
98             uart_rx_wakeup = 0xff;
99         }
100         goto _l0; // exit
101     }
102     if(BAUDCONbits.ABDEN == 1) { // Still configure baudrate
103         goto _l0; // Exit
104     }
105
106     if(RCSTAbits.OERR == 0) {
107         if(RCSTAbits.FERR == 0) {
108             uart_rx_sts = 0; // Clear error
109             c = RCREG;
110             if(c == UART_CH_XOFF) {
111                 uart_tx_xon = 0;  // XOFF Sequence for TX
112              } else if(c == UART_CH_XON) { // XON Sequence for TX
113                  uart_tx_xon = 0xff;
114              }  else if(uart_rx_bytes < UART_BUF_SIZE) { //
115                         uart_rfifo[uart_rx_wptr++] = c;
116                         if(uart_rx_wptr >= UART_BUF_SIZE) uart_rx_wptr = 0;
117                         uart_rx_bytes++;
118                         if(uart_rx_bytes >= UART_BUF_SIZE) uart_rx_bytes = UART_BUF_SIZE;
119              }
120         } else { // Frame Error
121          uart_rx_sts != UART_FRAMEERROR;
122         }
123     } else {
124          uart_rx_sts != UART_OVERFLOW;
125     }
126
127 _l0:  // Exit
128  PIR1bits.RC1IF = 0;
129  return;
130 }
131
132 /*
133  * Pull char from RX FIFO.
134  */
135 unsigned char uart_pullchar(void)
136 {
137     unsigned char c;
138     while(PIR1bits.RC1IF == 1) {
139         idle(100); // Wait for RX completed
140     }
141     if(uart_rx_bytes <= 0) return 0; // EMPTY
142     c = uart_rfifo[uart_rx_rptr++];
143     if(uart_rx_rptr > UART_BUF_SIZE) uart_rx_rptr = 0;
144     uart_rx_bytes--;
145     if(uart_rx_bytes <= 0) uart_rx_bytes = 0;
146     return c;
147 }
148
149 unsigned char uart_pushchar(unsigned char c, unsigned int timeout)
150 {
151     unsigned int i;
152     if(timeout != 0){
153         for(i = timeout; i > 0; i--){
154             if((uart_tx_xon != 0) && (TXSTAbits.TRMT1 == 1)) break;
155             idle(100);
156         }
157         if(i != 0) goto _l1;  // Send and return;
158         return UART_TIMEOUT; // Timeout
159     }
160     if((TXSTAbits.TRMT1 == 0) || (uart_tx_xon == 0)) return UART_TIMEOUT; // If timeout=0 return immidiately.
161 _l1:
162     TXREG = c;
163     return 0;
164 }
165
166 void uart_pushxon(unsigned int timeout)
167 {
168     unsigned int i;
169     if(uart_rx_wakeup == 0) return;
170     if(timeout != 0) {
171         for(i = timeout; i > 0; i--){
172             if(TXSTAbits.TRMT1 == 1) break;
173             idle(100); // 100us
174         }
175         return;
176     } else {
177         while(TXSTAbits.TRMT1 == 0) idle(100);
178     }
179     TXREG = UART_CH_XON;
180 }
181
182 void uart_pushxoff(unsigned int timeout)
183 {
184     unsigned int i;
185     if(uart_rx_wakeup == 0) return;
186     if(timeout != 0) {
187         for(i = timeout; i > 0; i--){
188             if(TXSTAbits.TRMT1 == 1) break;
189             idle(100); // 100us
190         }
191         return;
192     } else {
193         while(TXSTAbits.TRMT1 == 0) idle(100);
194     }
195     TXREG = UART_CH_XOFF;
196 }
197
198 void uart_break(void)
199 {
200     TXSTAbits.SENDB1 = 1;
201 }
202
203 unsigned char uart_getstat(void)
204 {
205     unsigned char s = uart_rx_sts;
206     if(uart_rx_wakeup != 0) s |= UART_WAKEUP;
207     return s;
208 }