Initial release
[fw/sdcc] / device / lib / ser_ir_cts_rts.c
diff --git a/device/lib/ser_ir_cts_rts.c b/device/lib/ser_ir_cts_rts.c
new file mode 100755 (executable)
index 0000000..9be6d72
--- /dev/null
@@ -0,0 +1,200 @@
+/*-------------------------------------------------------------------------
+  ser_ir.c - source file for serial routines
+
+  Written By - Josef Wolf <jw@raven.inka.de> (1999)
+
+  Revisions:
+  1.0  Bela Torok <bela.torok.kssg.ch> Jul. 2000
+  RTS / CTS protocol added
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+  In other words, you are welcome to use, share and improve this program.
+  You are forbidden to forbid anyone else to use, share and improve
+  what you give them.   Help stamp out software-hoarding!
+
+-------------------------------------------------------------------------*/
+
+/* This file implements a serial interrupt handler and its supporting
+* routines. Compared with the existing serial.c and _ser.c it has
+* following advantages:
+* - You can specify arbitrary buffer sizes (umm, up to 255 bytes),
+*   so it can run on devices with _little_ memory like at89cx051.
+* - It won't overwrite characters which already are stored in the
+*   receive-/transmit-buffer.
+* - It checks receiver first to minimize probability for overruns
+*   in the serial receiver.
+*/
+
+/* BUG: those definitions (and the #include) should be set dynamically
+* (while linking or at runtime) to make this file a _real_ library.
+*/
+
+/* RTS/CTS protocol howto:
+
+
+   Shematic of cable for RTS/CTS protocol (B. Torok - Jun. 2000)
+
+<- DB9 female connector -><- RS232 driver/receiver -><- 8051 system ->
+   connect to PC             e.g. MAX232
+
+                             RS232         TTL
+                             level         level
+
+   DCD    DTR                
+   Pin1---Pin4               
+                            Transmitters/Receivers
+   RXD
+   Pin2-----------------------------<<<-------------------TXD
+
+   TXD
+   Pin3----------------------------->>>-------------------RXD
+
+   GND
+   Pin5---------------------------------------------------GND
+
+   DSR    CTS
+   Pin6---Pin8----------------------<<<-------------------CTS (see #define CTS)
+
+   RTS
+   Pin7----------------------------->>>-------------------RTS (see #define RTS)
+*/
+
+
+#include <8051.h>
+#include "ser_ir.h"
+
+#define TXBUFLEN 3
+#define RXBUFLEN 18      // The minimum rx buffer size for safe communications
+                         // is 17. (The UART in the PC has a 16-byte FIFO.)
+// TXBUFLEN & RXBUFLEN can be highher if rxbuf[] and txbuf[] is in xdata, max size is limited to 256!
+
+#define THRESHOLD 16
+#define ENABLE    0
+#define DISABLE   1
+
+#define CTS P3_6          // CTS & RTS can be assigned to any free pins
+#define RTS P3_7
+
+static unsigned char rxbuf[RXBUFLEN], txbuf[TXBUFLEN];
+static unsigned char rxcnt, txcnt, rxpos, txpos;
+static unsigned char busy;
+
+void ser_init()
+{
+  ES = 0;
+  rxcnt = txcnt = rxpos = txpos = 0;  // init buffers
+  busy = 0;
+  SCON = 0x50;               // mode 1 - 8-bit UART
+  PCON |= 0x80;              // SMOD = 1;
+  TMOD &= 0x0f;              // use timer 1
+  TMOD |= 0x20;
+//  TL1 = TH1 = 256 - 104;      // 600bps with 12 MHz crystal
+//  TL1 = TH1 = 256 - 52;      // 1200bps with 12 MHz crystal
+//  TL1 = TH1 = 256 - 26;      // 2400bps with 12 MHz crystal
+  TL1 = TH1 = 256 - 13;      // 4800bps with 12 MHz crystal
+
+  TR1 = 1;                   // Enable timer 1
+  ES = 1;
+
+  CTS = ENABLE;
+}
+
+void ser_handler(void) interrupt 4
+{
+  if (RI) {
+    RI = 0;
+    /* don't overwrite chars already in buffer */
+    if(rxcnt < RXBUFLEN) rxbuf [(rxpos + rxcnt++) % RXBUFLEN] = SBUF;
+    if(rxcnt >= (RXBUFLEN - THRESHOLD)) CTS = DISABLE;
+  }
+
+  if (TI) {
+    TI = 0;
+    if (busy = txcnt) {   /* Assignment, _not_ comparison! */
+      txcnt--;
+      SBUF = txbuf[txpos++];
+      if(txpos >= TXBUFLEN) txpos = 0;
+    }
+  }
+}
+
+void ser_putc(unsigned char c)
+{
+  while(txcnt >= TXBUFLEN);   // wait for room in buffer
+
+  while(RTS == DISABLE);
+
+  ES = 0;
+  if (busy) {
+    txbuf[(txpos + txcnt++) % TXBUFLEN] = c;
+  } else {
+    SBUF = c;
+    busy = 1;
+  }
+  ES = 1;
+}
+
+unsigned char ser_getc(void)
+{
+  unsigned char c;
+
+  while (!rxcnt) {        // wait for a character
+    CTS = ENABLE;
+  }
+
+  ES = 0;
+  rxcnt--;
+  c = rxbuf[rxpos++];
+  if (rxpos >= RXBUFLEN) rxpos = 0;
+  ES = 1;
+  return (c);
+}
+
+#pragma SAVE
+#pragma NOINDUCTION
+void ser_puts(unsigned char *s)
+{
+  unsigned char c;
+  while (c= *s++) {
+    if (c == LF) ser_putc(CR);
+    ser_putc (c);
+  }
+}
+#pragma RESTORE
+
+void ser_gets(unsigned char *s, unsigned char len)
+{
+  unsigned char pos, c;
+
+  pos = 0;
+  while (pos <= len) {
+    c = ser_getc();
+    if (c == CR) continue;        // discard CR's
+    s[pos++] = c;
+    if (c == LF) break;           // NL terminates
+  }
+  s[pos] = '\0';                  // terminate string
+}
+
+unsigned char ser_can_xmt(void)
+{
+  return TXBUFLEN - txcnt;
+}
+
+unsigned char ser_can_rcv(void)
+{
+  return rxcnt;
+}
\ No newline at end of file