51069fe67e6fbda31f76430b43d56c4aae12ec91
[fw/sdcc] / device / lib / ser_ir_cts_rts.c
1 /*-------------------------------------------------------------------------
2   ser_ir.c - source file for serial routines
3
4   Written By - Josef Wolf <jw@raven.inka.de> (1999)
5
6   Revisions:
7   1.0  Bela Torok <bela.torok.kssg.ch> Jul. 2000
8   RTS / CTS protocol added
9
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27
28 -------------------------------------------------------------------------*/
29
30 /* This file implements a serial interrupt handler and its supporting
31 * routines. Compared with the existing serial.c and _ser.c it has
32 * following advantages:
33 * - You can specify arbitrary buffer sizes (umm, up to 255 bytes),
34 *   so it can run on devices with _little_ memory like at89cx051.
35 * - It won't overwrite characters which already are stored in the
36 *   receive-/transmit-buffer.
37 */
38
39 /* BUG: those definitions (and the #include) should be set dynamically
40 * (while linking or at runtime) to make this file a _real_ library.
41 */
42
43 /* RTS/CTS protocol howto:
44
45
46    Shematic of cable for RTS/CTS protocol (B. Torok - Jun. 2000)
47
48 <- DB9 female connector -><- RS232 driver/receiver -><- 8051 system ->
49    connect to PC             e.g. MAX232
50
51                              RS232         TTL
52                              level         level
53
54    DCD    DTR                
55    Pin1---Pin4               
56                             Transmitters/Receivers
57    RXD
58    Pin2-----------------------------<<<-------------------TXD
59
60    TXD
61    Pin3----------------------------->>>-------------------RXD
62
63    GND
64    Pin5---------------------------------------------------GND
65
66    DSR    CTS
67    Pin6---Pin8----------------------<<<-------------------CTS (see #define CTS)
68
69    RTS
70    Pin7----------------------------->>>-------------------RTS (see #define RTS)
71 */
72
73
74 #include <8051.h>
75 #include "ser_ir.h"
76
77 #define TXBUFLEN 3
78 #define RXBUFLEN 18      // The minimum rx buffer size for safe communications
79                          // is 17. (The UART in the PC has a 16-byte FIFO.)
80 // TXBUFLEN & RXBUFLEN can be highher if rxbuf[] and txbuf[] is in xdata, max size is limited to 256!
81
82 #define THRESHOLD 16
83 #define ENABLE    0
84 #define DISABLE   1
85
86 #define CTS P3_6          // CTS & RTS can be assigned to any free pins
87 #define RTS P3_7
88
89 // You might want to specify idata, pdata or xdata for the buffers
90 static unsigned char rxbuf[RXBUFLEN], txbuf[TXBUFLEN];
91 static unsigned char rxcnt, txcnt, rxpos, txpos;
92 static bit busy;
93
94 void ser_init()
95 {
96   ES = 0;
97   rxcnt = txcnt = rxpos = txpos = 0;  // init buffers
98   busy = 0;
99   SCON = 0x50;               // mode 1 - 8-bit UART
100   PCON |= 0x80;              // SMOD = 1;
101   TMOD &= 0x0f;              // use timer 1
102   TMOD |= 0x20;
103 //  TL1 = TH1 = 256 - 104;      // 600bps with 12 MHz crystal
104 //  TL1 = TH1 = 256 - 52;      // 1200bps with 12 MHz crystal
105 //  TL1 = TH1 = 256 - 26;      // 2400bps with 12 MHz crystal
106   TL1 = TH1 = 256 - 13;      // 4800bps with 12 MHz crystal
107
108   TR1 = 1;                   // Enable timer 1
109   ES = 1;
110
111   CTS = ENABLE;
112 }
113
114 void ser_handler(void) interrupt 4
115 {
116   if (RI) {
117     RI = 0;
118     /* don't overwrite chars already in buffer */
119     if(rxcnt < RXBUFLEN) rxbuf [(unsigned char)(rxpos + rxcnt++) % RXBUFLEN] = SBUF;
120     if(rxcnt >= (RXBUFLEN - THRESHOLD)) CTS = DISABLE;
121   }
122
123   if (TI) {
124     TI = 0;
125     if (busy = txcnt) {   /* Assignment, _not_ comparison! */
126       txcnt--;
127       SBUF = txbuf[txpos++];
128       if(txpos >= TXBUFLEN) txpos = 0;
129     }
130   }
131 }
132
133 void ser_putc(unsigned char c)
134 {
135   while(txcnt >= TXBUFLEN);   // wait for room in buffer
136
137   while(RTS == DISABLE);
138
139   ES = 0;
140   if (busy) {
141     txbuf[(unsigned char)(txpos + txcnt++) % TXBUFLEN] = c;
142   } else {
143     SBUF = c;
144     busy = 1;
145   }
146   ES = 1;
147 }
148
149 unsigned char ser_getc(void)
150 {
151   unsigned char c;
152
153   while (!rxcnt) {        // wait for a character
154     CTS = ENABLE;
155   }
156
157   ES = 0;
158   rxcnt--;
159   c = rxbuf[rxpos++];
160   if (rxpos >= RXBUFLEN) rxpos = 0;
161   ES = 1;
162   return (c);
163 }
164
165 #pragma save
166 #pragma noinduction
167 void ser_puts(unsigned char *s)
168 {
169   unsigned char c;
170   while (c= *s++) {
171     if (c == '\n') ser_putc('\r');
172     ser_putc (c);
173   }
174 }
175 #pragma restore
176
177 void ser_gets(unsigned char *s, unsigned char len)
178 {
179   unsigned char pos, c;
180
181   pos = 0;
182   while (pos <= len) {
183     c = ser_getc();
184     if (c == '\r') continue;        // discard CR's
185     s[pos++] = c;
186     if (c == '\n') break;           // NL terminates
187   }
188   s[pos] = '\0';                  // terminate string
189 }
190
191 unsigned char ser_can_xmt(void)
192 {
193   return TXBUFLEN - txcnt;
194 }
195
196 unsigned char ser_can_rcv(void)
197 {
198   return rxcnt;
199 }