Thursday, December 17, 2009

COMTASK.C

/*****************************************************************************
            COMMUNICATION TASK FOR 68HC16-BASED TERMO-LOGGER
                                  WITH
                    SLIP PROTOCOL AS DATA-LINK LAYER

                             (c) June 1995
                              by M. Lutfi
                        Engineering Physics Dept
                    Faculty of Industrial Technology
                       Institut Teknologi Bandung

        =======================================================

      Each received character is copied into  a queue by the interrupt
      routine and each character will be send by SCI_trm_task
      periodically then gives a semaphore to other tasks via SCI_SEMA.
      Before data copied to other segment/buffer, data must be
      depacketized. ComTask always calls Depacketizer routine when
      he receives data. MCX16 manages timing each period.

      We don't need interrupt handler, because we don't use it.
      To transmitting a character, just put it into SCI_TRM_QUEUE


      If needed, QSPI routines can be added as request.

                           (c) M. Lutfi, 1995
             Last updated: 5-June-1995 at MKN, Suropati 231
******************************************************************************/
#define _WSC_

#include "mcx16.h"
#include "sysdef.h"


#define SCI_IV       0x3A           /* interrupt vector number */
#define IL_QSPI         1           /* QSPI has lowest priority */
#define IL_SCI          7           /* SCI has highest priority */
#define SIZE          512           /* buffer size */
#define TDRE        0x100           /* transmit ready bit */
#define SYS_CLOCK   16780000L       /* HC16EVB's system clock */
#define BAUD_RATE(bps)     (SYS_CLOCK/(bps*32))

/*
  SLIP special character codes
*/
#define FR_END              0xC0 /* indicates end of packet */
#define FR_ESC              0xDB /* indicates byte stuffing */
#define T_FR_END            0xDC /* FR_ESC T_FR_END means END data byte */
#define T_FR_ESC            0xDD /* FR_ESC T_FR_ESC means ESC data byte */

#ifdef _WSC_    /* if WSC compiler */
    #include <wslxa.h>
    #include "_qsm.h"
    #include "sysdef.h"

#else       /* this not for WSC compiler */
    #include <dos.h>
    #include <stdio.h>
    #define FOREVER    for(;;)
    int scsr;
    int scdr;
    int qmcr;
    int qilr;
    int qilr_ilqspi;
    int qilr_ilsci;
    int qivr;
    int sccr0;
    int sccr1, sccr1_pe, sccr1_m, sccr1_te, sccr1_re;
#endif

   /* below are values for SCBR baud rates */
#define BPS_110          1748
#define BPS_600           874
#define BPS_1200          437
#define BPS_2400          218
#define BPS_4800          109
#define BPS_9600           55
#define BPS_19200           27
#define BPS_32768           16
#define    BPS_38400           14
#define BPS_500000          1


/**************************** GLOBAL VARIABLES *******************************
char in_char;
char out_char;
******************************************************************************/


/******************************************************************************
                              SEND_PACKET:
        sends a packet of length "len", starting at location "p"
******************************************************************************/
void send_packet(void *data, int len)
{
   /* send an initial END character to flush out any data (garbage) that
    * have accumulated in the receiver due to line noise
    */
   char *p;

   p = (char *)data;
   send_char(FR_END);

   /* for each byte in the packet, send the appropriate character
    * sequence
    */
   while (len--) {
      if (*p==FR_END) {
          send_char(FR_ESC);
          send_char(T_FR_END);
      }
      else
      if (*p==FR_ESC) {
         send_char(FR_ESC);
         send_char(T_FR_ESC);
      }
      else   /* otherwise, we just send the character */
         send_char(*p);
      p++;
   }
   /* tell the receiver that we're done sending the packet */
   send_char(FR_END);
}


/***************************** RECV_PACKET ***********************************
            receive a packet into the queue located at "p".
 *      If more than len bytes are received, the packet will be
 *      truncated.
 *      Returns the number of bytes stored in the buffer.
 *****************************************************************************/
int recv_packet(void *p, int len)
{
   char c;
   int received = 0;

   /* sit in a loop reading bytes until we put together a whole packet.
    * Make sure not to copy them into the packet if we run out of room.
    */
   while (1) {
      /* get a character to process */
      c = get_char();

      /* handle bytestuffing if necessary */
      if (c==FR_END) {
         /* a minor optimization: if there is no data in the packet,
          * ignore it. This is meant to avoid bothering IP with all
          * the empty packets generated by the duplicate FR_END char-
          * racters which are in turn sent to try to detect line noise.
          */
          if (received)
            return (received);
      }
      else
      if (c==FR_ESC) {
         c = get_char();

         /* if "c" is not and FR_ESC character, wait and get another
          * character and then figure out what to store in the packet
          * based on that.
          */
          if (c==T_FR_END)
            c = FR_END;
          else
          if (c==T_FR_ESC)
            c = FR_ESC;
          goto STORE;
      }
      else {
      STORE:
         /* here we fall into the default handler and let it store
          * the charater for us
          */
          if (received < len)
            p[received++] = c;
      }
   }
   _mcx_signal(SCI_RCV_SEMA);
}


/****************************************************************************
                       SCI driver Initialization
 > Sets up the ACIA and starts an infinite loop of receive transmit
 > QSM configuration summary:
   * After reset, the QSM remains in an idle state, requiring initialization
     of several registers before any serial operations may begin execution.
   * The type of serial frame (8 or 9 bit) and the use of partiy must be
     determined by M. PE and PT.
   * For receive operation, WAKE, RWU, ILT, ILIE must be considered.
     The receiver must be enabled (RE) and, usually, RIE should be set.
   * For transmit operation, the transmitter must be enabled (TE) and,
     usually, TIE should be set. The use of wired-OR mode (WOMS) must also
     be decided. Once the transmitter is configured, data is not sent
     until TDRE and TC are cleared. To clear TDRE and TC, the SCSR read
     must be followed by a write to SCDR (either the lower byte or the
     entire word).
   * QIVR should be programmed to one of the user-defined vectors ($40-$FF)
     during initialization of the QSM.
     After reset, QIVR determines which two vectors in the exception vector
     table are to be used for QSM interrupts. The QSPI and SCI submodules
     have separate interrupt vectors adjacent to each other.
     Both submodules use the same interrupt vector which LSB:
        1: interrupt generated by QSPI
        0: interrupt generated by QSCI
 > Detail Configurations in QSM:
   * QMCR:
        STOP = 0 (Normal QSM clock operation)
        FRZ1 = 0 (Ignore the FREEZE signal on the IMB)
        SUPV = 1 (supervisor access)
        IARB = $A (priority = 10; $F = highest priority, used by timer)
   * QILR:
        ILQSPI = 1 (lowest priority)
        ILSCI  = 7 (highest priority)
        QIVR   = set to SCI interrupt handler's address

****************************************************************************/

No comments:

Post a Comment