
<font color="#0000ff">/*</font><font color="#0000ff">-------------------------------------------------------------------------</font>
<font color="#0000ff">  ser_ir.c - source file for serial routines </font>
<font color="#0000ff">  </font>
<font color="#0000ff">  Written By - Josef Wolf &lt;jw@raven.inka.de&gt; (1999) </font>
<font color="#0000ff">  </font>
<font color="#0000ff">         This program is free software; you can redistribute it and/or modify it</font>
<font color="#0000ff">         under the terms of the GNU General Public License as published by the</font>
<font color="#0000ff">         Free Software Foundation; either version 2, or (at your option) any</font>
<font color="#0000ff">         later version.</font>
<font color="#0000ff">         </font>
<font color="#0000ff">         This program is distributed in the hope that it will be useful,</font>
<font color="#0000ff">         but WITHOUT ANY WARRANTY; without even the implied warranty of</font>
<font color="#0000ff">         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</font>
<font color="#0000ff">         GNU General Public License for more details.</font>
<font color="#0000ff">         </font>
<font color="#0000ff">         You should have received a copy of the GNU General Public License</font>
<font color="#0000ff">         along with this program; if not, write to the Free Software</font>
<font color="#0000ff">         Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.</font>
<font color="#0000ff">         </font>
<font color="#0000ff">         In other words, you are welcome to use, share and improve this program.</font>
<font color="#0000ff">         You are forbidden to forbid anyone else to use, share and improve</font>
<font color="#0000ff">         what you give them.   Help stamp out software-hoarding!</font>

<font color="#0000ff">-------------------------------------------------------------------------*/</font>
<font color="#a020f0">#include </font><font color="#ff00ff">&quot;ser_ir.h&quot;</font>

<font color="#0000ff">/*</font><font color="#0000ff"> This file implements a serial interrupt handler and its supporting</font>
<font color="#0000ff">* routines. Compared with the existing serial.c and _ser.c it has</font>
<font color="#0000ff">* following advantages:</font>
<font color="#0000ff">* - You can specify arbitrary buffer sizes (umm, up to 255 bytes),</font>
<font color="#0000ff">*   so it can run on devices with _little_ memory like at89cx051.</font>
<font color="#0000ff">* - It won't overwrite characters which already are stored in the</font>
<font color="#0000ff">*   receive-/transmit-buffer.</font>
<font color="#0000ff">* - It checks receiver first to minimize probability for overruns</font>
<font color="#0000ff">*   in the serial receiver.</font>
<font color="#0000ff">*/</font>

<font color="#0000ff">/*</font><font color="#0000ff"> BUG: those definitions (and the #include) should be set dynamically</font>
<font color="#0000ff">* (while linking or at runtime) to make this file a _real_ library.</font>
<font color="#0000ff">*/</font>
<font color="#a020f0">#include </font><font color="#ff00ff">&lt;8051.h&gt;</font>
<font color="#a020f0">#define XBUFLEN </font><font color="#ff00ff">10</font>
<font color="#a020f0">#define RBUFLEN </font><font color="#ff00ff">10</font>

<font color="#2e8b57"><b>static</b></font> <font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> rbuf[RBUFLEN], xbuf[XBUFLEN];
<font color="#2e8b57"><b>static</b></font> <font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> rcnt, xcnt, rpos, xpos;
<font color="#2e8b57"><b>static</b></font> <font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> busy;

<font color="#2e8b57"><b>void</b></font> ser_init (<font color="#2e8b57"><b>void</b></font>)
{
   ES = <font color="#ff00ff">0</font>;
   rcnt = xcnt = rpos = xpos = <font color="#ff00ff">0</font>;  <font color="#0000ff">/*</font><font color="#0000ff"> init buffers */</font>
   busy = <font color="#ff00ff">0</font>;
   SCON = <font color="#ff00ff">0x50</font>;
   PCON |= <font color="#ff00ff">0x80</font>;                   <font color="#0000ff">/*</font><font color="#0000ff"> SMOD = 1; */</font>
   TMOD &amp;= <font color="#ff00ff">0x0f</font>;                   <font color="#0000ff">/*</font><font color="#0000ff"> use timer 1 */</font>
   TMOD |= <font color="#ff00ff">0x20</font>;
   TL1 = -<font color="#ff00ff">3</font>; TH1 = -<font color="#ff00ff">3</font>; TR1 = <font color="#ff00ff">1</font>;    <font color="#0000ff">/*</font><font color="#0000ff"> 19200bps with 11.059MHz crystal */</font>
   ES = <font color="#ff00ff">1</font>;
}

<font color="#2e8b57"><b>void</b></font> ser_handler (<font color="#2e8b57"><b>void</b></font>) interrupt <font color="#ff00ff">4</font>
{
   <font color="#804040"><b>if</b></font> (RI) {
           RI = <font color="#ff00ff">0</font>;
           <font color="#0000ff">/*</font><font color="#0000ff"> don't overwrite chars already in buffer */</font>
           <font color="#804040"><b>if</b></font> (rcnt &lt; RBUFLEN)
                   rbuf [(rpos+rcnt++) % RBUFLEN] = SBUF;
   }
   <font color="#804040"><b>if</b></font> (TI) {
           TI = <font color="#ff00ff">0</font>;
           <font color="#804040"><b>if</b></font> (busy = xcnt) {   <font color="#0000ff">/*</font><font color="#0000ff"> Assignment, _not_ comparison! */</font>
                   xcnt--;
                   SBUF = xbuf [xpos++];
                   <font color="#804040"><b>if</b></font> (xpos &gt;= XBUFLEN)
                           xpos = <font color="#ff00ff">0</font>;
           }
   }
}

<font color="#2e8b57"><b>void</b></font> ser_putc (<font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> c)
{
   <font color="#804040"><b>while</b></font> (xcnt &gt;= XBUFLEN) <font color="#0000ff">/*</font><font color="#0000ff"> wait for room in buffer */</font>
           ;
   ES = <font color="#ff00ff">0</font>;
   <font color="#804040"><b>if</b></font> (busy) {
           xbuf[(xpos+xcnt++) % XBUFLEN] = c;
   } <font color="#804040"><b>else</b></font> {
           SBUF = c;
           busy = <font color="#ff00ff">1</font>;
   }
   ES = <font color="#ff00ff">1</font>;
}

<font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> ser_getc (<font color="#2e8b57"><b>void</b></font>)
{
   <font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> c;
   <font color="#804040"><b>while</b></font> (!rcnt)   <font color="#0000ff">/*</font><font color="#0000ff"> wait for character */</font>
           ;
   ES = <font color="#ff00ff">0</font>;
   rcnt--;
   c = rbuf [rpos++];
   <font color="#804040"><b>if</b></font> (rpos &gt;= RBUFLEN)
           rpos = <font color="#ff00ff">0</font>;
   ES = <font color="#ff00ff">1</font>;
   <font color="#804040"><b>return</b></font> (c);
}
<font color="#a020f0">#pragma save</font>
<font color="#a020f0">#pragma noinduction</font>
<font color="#2e8b57"><b>void</b></font> ser_puts (<font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> *s)
{
   <font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> c;
   <font color="#804040"><b>while</b></font> (c=*s++) {
           <font color="#804040"><b>if</b></font> (c == <font color="#6a5acd">'\n'</font>) ser_putc (<font color="#6a5acd">'\r'</font>);
           ser_putc (c);
   }
}
<font color="#a020f0">#pragma restore</font>
<font color="#2e8b57"><b>void</b></font> ser_gets (<font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> *s, <font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> len)
{
   <font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> pos, c;

   pos = <font color="#ff00ff">0</font>;
   <font color="#804040"><b>while</b></font> (pos &lt;= len) {
           c = ser_getc ();
           <font color="#804040"><b>if</b></font> (c == <font color="#6a5acd">'\r'</font>) <font color="#804040"><b>continue</b></font>;        <font color="#0000ff">/*</font><font color="#0000ff"> discard CR's */</font>
           s[pos++] = c;
           <font color="#804040"><b>if</b></font> (c == <font color="#6a5acd">'\n'</font>) <font color="#804040"><b>break</b></font>;           <font color="#0000ff">/*</font><font color="#0000ff"> NL terminates */</font>
   }
   s[pos] = <font color="#6a5acd">'\0'</font>;
}

<font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> ser_can_xmt (<font color="#2e8b57"><b>void</b></font>)
{
   <font color="#804040"><b>return</b></font> XBUFLEN - xcnt;
}

<font color="#2e8b57"><b>unsigned</b></font> <font color="#2e8b57"><b>char</b></font> ser_can_rcv (<font color="#2e8b57"><b>void</b></font>)
{
   <font color="#804040"><b>return</b></font> rcnt;
}
