OSDN Git Service

[Schematic][v2.0] Add pullup for RX, issue of unconnected to USB.
[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 = 0b10010000; //SPEN, 8bit, ASYNC, CREN = 0
60     BAUDCON = 0b00001010; // IDLE High, BRG16, ABDEN, WUE
61     TXSTA = 0b00100000; //8bit, ASYNC, TXEN, Break
62     PIE1bits.TX1IE = 0;
63     PIE1bits.RC1IE = 1;
64     uart_rx_wakeup = 0;
65     SPBRGH = 51 / 256;
66     SPBRG = 51 % 256;
67 }
68
69 void uart_wakeup(void)
70 {
71     PIR1bits.TX1IF = 0;
72     PIR1bits.RC1IF = 0;
73     IPR1bits.TX1IP = 0;  // Low
74     IPR1bits.RC1IP = 1; // High
75     RCSTA = 0b10010000; //SPEN, 8bit, ASYNC, CREN
76     BAUDCON = 0b00001010; // IDLE High, BRG16, ABDEN, WUE
77     TXSTA = 0b00100000; //8bit, ASYNC, TXEN, Break
78     PIE1bits.TX1IE = 0;
79     PIE1bits.RC1IE = 1;
80 //   uart_rx_wakeup = 0xff;
81    SPBRGH = 51 / 256;
82    SPBRG = 51 % 256;
83 }
84
85 void uart_init(void)
86 {
87     uart_rx_rptr = 0;
88     uart_rx_wptr = 0;
89     uart_rx_bytes = 0;
90     uart_rx_wakeup = 0;
91     uart_rx_xon = 0xff;
92     uart_tx_xon = 0xff;
93     uart_sleep();
94 }
95
96
97 void uart_inthdr_rx(void)
98 {
99     unsigned char c;
100 #if 1
101     if(uart_rx_wakeup == 0){
102         if(BAUDCONbits.WUE != 1){ // Okay, Wakeup interrupt
103             uart_rx_wakeup = 0xff;
104         }
105         goto _l0; // exit
106     }
107     if(BAUDCONbits.ABDEN == 1) { // Still configure baudrate
108         goto _l0; // Exit
109     }
110 #endif
111     if(RCSTAbits.OERR == 0) {
112         if(RCSTAbits.FERR == 0) {
113             uart_rx_sts = 0; // Clear error
114             c = RCREG;
115             if(c == UART_CH_XOFF) {
116                 uart_tx_xon = 0;  // XOFF Sequence for TX
117              } else if(c == UART_CH_XON) { // XON Sequence for TX
118                  uart_tx_xon = 0xff;
119              }  else { //if(uart_rx_bytes < UART_BUF_SIZE) { //
120                         uart_rfifo[uart_rx_wptr++] = c;
121                         if(uart_rx_wptr >= UART_BUF_SIZE) uart_rx_wptr = 0;
122                         uart_rx_bytes++;
123                         if(uart_rx_bytes >= UART_BUF_SIZE) uart_rx_bytes = UART_BUF_SIZE;
124 //              uart_pushchar(c, 0x0000);
125              }
126         } else { // Frame Error
127          uart_rx_sts != UART_FRAMEERROR;
128         }
129     } else {
130          uart_rx_sts != UART_OVERFLOW;
131     }
132
133 _l0:  // Exit
134  PIR1bits.RC1IF = 0;
135  RCSTAbits.CREN = 1;
136  return;
137 }
138
139 /*
140  * Pull char from RX FIFO.
141  */
142 unsigned char uart_pullchar(void)
143 {
144     unsigned char c;
145     while(PIR1bits.RC1IF == 1) {
146         idle(100); // Wait for RX completed
147     }
148     if(uart_rx_bytes <= 0) return 0; // EMPTY
149     c = uart_rfifo[uart_rx_rptr++];
150     if(uart_rx_rptr > UART_BUF_SIZE) uart_rx_rptr = 0;
151     uart_rx_bytes--;
152     if(uart_rx_bytes <= 0) uart_rx_bytes = 0;
153     return c;
154 }
155
156 unsigned char uart_pushchar(unsigned char c, unsigned int timeout)
157 {
158     unsigned int i;
159     if(timeout != 0){
160         for(i = timeout; i > 0; i--){
161             if((uart_tx_xon != 0) && (TXSTAbits.TRMT1 == 1)) break;
162             idle(100);
163         }
164         if(i != 0) goto _l1;  // Send and return;
165         return UART_TIMEOUT; // Timeout
166     }
167     if((TXSTAbits.TRMT1 == 0) || (uart_tx_xon == 0)) return UART_TIMEOUT; // If timeout=0 return immidiately.
168 _l1:
169     TXREG = c;
170     return 0;
171 }
172
173 void uart_pushxon(unsigned int timeout)
174 {
175     unsigned int i;
176     if(uart_rx_wakeup == 0) return;
177     if(timeout != 0) {
178         for(i = timeout; i > 0; i--){
179             if(TXSTAbits.TRMT1 == 1) break;
180             idle(100); // 100us
181         }
182         return;
183     } else {
184         while(TXSTAbits.TRMT1 == 0) idle(100);
185     }
186     TXREG = UART_CH_XON;
187 }
188
189 void uart_pushxoff(unsigned int timeout)
190 {
191     unsigned int i;
192     if(uart_rx_wakeup == 0) return;
193     if(timeout != 0) {
194         for(i = timeout; i > 0; i--){
195             if(TXSTAbits.TRMT1 == 1) break;
196             idle(100); // 100us
197         }
198         return;
199     } else {
200         while(TXSTAbits.TRMT1 == 0) idle(100);
201     }
202     TXREG = UART_CH_XOFF;
203 }
204
205 void uart_break(void)
206 {
207     TXSTAbits.SENDB1 = 1;
208 }
209
210 unsigned char uart_getstat(void)
211 {
212     unsigned char s = uart_rx_sts;
213     if(uart_rx_wakeup != 0) s |= UART_WAKEUP;
214     return s;
215 }