prefect
Home Engineering Publications
DACS: SCI Serial Driver Code, SCIserial.c
 
  next up previous contents
Next: ACIA Serial Driver Header Up: Firmware Library, dacslib Previous: SCI Serial Driver Header,   Contents

SCI Serial Driver Code, SCIserial.c

The following code provides serial driver functions for the 68HC11 SCI serial interface. Frame handling functions are provided as well as simple serial access routines.
/*****************************************************************************
 * DACS : Distributed Audio Control System
 *============================================================================
 *         File: SCIserial.c
 *       Author: Stephen S. Richardson
 * Date Created: 04.14.97
 *  Environment: ICC11 v4.0, 68HC11 target
 *        Build: library, not standalone
 *============================================================================
 * The code, executables, documentation, firmware images, and all related
 * material of DACS are  
 * Copyright (C) 1997 Stephen S. Richardson - ALL RIGHTS RESERVED
 *****************************************************************************
 * Source code control:
 *
 * $Id: SCIserial.c,v 1.3 1997/07/13 01:23:16 prefect Exp prefect $
 *
 *****************************************************************************/

#include <hc11.h>
#include "SCIserial.h"

#ifdef _MIXER
#include "pbusdefn.h"
#endif


/*****************************************************************************
 * SCI_prep_raw
 *
 * initializes a raw frame
 *****************************************************************************/
void SCI_prep_raw (struct raw_frame *raw)
{
  int i;

  raw->len=0;
  raw->cur=0;
  raw->done=0;
  raw->dleflag=0;
  raw->stflag=0;
  for (i=0;i<MAXPAYLOAD;i++) raw->data[i]=0;
}


/*****************************************************************************
 * SCI_prep_cooked
 *
 * initializes a cooked frame
 *****************************************************************************/
void SCI_prep_cooked (struct cooked_frame *cooked)
{
  int i;

  cooked->len=0;
  cooked->cur=0;
  cooked->done=1;

  for (i=0;i<MAXFRLEN;i++) cooked->data[i]=0;
}


/*****************************************************************************
 * SCI_data_to_cooked
 *
 * stuffs data into a cooked frame, setting parameters, etc.  output frame
 * is suitable to be directly output.
 *****************************************************************************/
void SCI_data_to_cooked (char *data, int len, struct cooked_frame *cooked)
{
  int i=0, j=0;
  char *p;

  /* start of frame: DLE+STX */
  cooked->data[j++]=DLE;
  cooked->data[j++]=STX;

  /* payload of frame (character stuffed) */
  p=data;

  for (i=0;i<len;i++) {
    if (*p == DLE) {
      cooked->data[j++]=DLE;
      cooked->data[j++]=DLE;
      p++;
    } else {
      cooked->data[j++]=*p;
      p++;
    }
  }

  /* end of frame: DLE+ETX */
  cooked->data[j++]=DLE;
  cooked->data[j++]=ETX;

  /* set length and other parameters */
  cooked->len=j;
  cooked->cur=0;
  cooked->done=0;
}


/*****************************************************************************
 * SCI_service
 *
 * perform necessary SCI operations to manipulate incoming and outgoing
 * frames, using a raw frame as an input buffer
 *****************************************************************************/
int SCI_service (struct raw_frame *inraw, struct cooked_frame *outfr)
{
  unsigned char ch;

  /* outgoing serial data & sci output port !busy? */

  if ( (SCSR&0x80) && (outfr->done==0) ) {

#ifdef _MIXER
    PBC_PC^=0x08;
#endif
    SCDR=outfr->data[outfr->cur];  /* output the current byte */
    
    /* have we transmitted all of it yet? */
    if (++outfr->cur < outfr->len) {
      /* not yet.. */
    } else {
      /* yes */
      outfr->done = 1;
    }
#ifdef _MIXER
    PBC_PC&=~0x08;
#endif
  }
   
  /* incoming data on sci and unfinished inraw frame? */

  if ( (SCSR&0x20) && (inraw->done==0) ) {
    /* -- yes, get and fill in the next byte */

#ifdef _MIXER
    PBC_PC^=0x04;
#endif
    ch = SCDR;

    if (inraw->dleflag) {
      /* the last byte received was a DLE */

      if (ch == DLE) {
	/* stuffed character */

	if (inraw->stflag == STX) {
	  /* save it if we're mid-frame */
	  inraw->data[inraw->cur] = DLE;
	  inraw->dleflag=0;

	  if (++inraw->cur < MAXPAYLOAD) {
	  } else {
	    inraw->done = ERRTOOBIG;
	  }
	}
      } else if (ch == STX) {
	/* start of frame */
	inraw->done = 0;
	inraw->cur = 0;
	inraw->dleflag=0;
	inraw->stflag=STX;

      } else if (ch == ETX) {
	/* end of frame */
	inraw->done = 1;
	inraw->dleflag=0;
	inraw->stflag=0;
      }

    } else {
      if (ch == DLE) {
	/* first DLE */
	inraw->dleflag = 1;
      } else {
	/* other data */

	if (inraw->stflag == STX) {
	  /* save it if we're mid-frame */
	  inraw->data[inraw->cur] = ch;
	  inraw->dleflag=0;
	  if (++inraw->cur < MAXPAYLOAD) {
	  } else {
	    inraw->done = ERRTOOBIG;
	  }
	}
      }
    }
#ifdef _MIXER
    PBC_PC&=~0x04;
#endif
  }
}


/*****************************************************************************
 * SCI_poll_in
 *
 * polled SCI input.  returns 1 if there was actually a character to get.
 *****************************************************************************/
int SCI_poll_in (unsigned char *c)
{
   if (SCSR&0x20) {
      *c=SCDR;
      return 1;
   } else {
      return 0;
   }
}


/*****************************************************************************
 * SCI_block_in
 *
 * blocking SCI input.  returns character.
 *****************************************************************************/
char SCI_block_in (void)
{
   while (!(SCSR&0x20));
   return (SCDR);
}


/*****************************************************************************
 * SCI_poll_in
 *
 * polled SCI input.  returns 1 if there was actually a character to get.
 *****************************************************************************/
void SCI_chout (unsigned char ch)
{
   while (!(SCSR&0x80));
   SCDR = ch;   
}


/*****************************************************************************
 * SCI_out
 *
 * SCI output (blocking)
 *****************************************************************************/
void SCI_out (char *s)
{
   char *t=s;
   
   while (*t!=0) {
     while (!(SCSR&0x80));
     SCDR = *t++;
   }
}


/*****************************************************************************
 * SCI_init
 *
 * initialize SCI port, 9600 baud, 8-N-1
 *****************************************************************************/
void SCI_init (void)
{
   BAUD=0x30;
   SCCR2=0x2C;
}


Steve Richardson 2000-07-06
Table of Contents

[PDF] [Whole document in PDF 1.9MB]

[more photos and information]

 
Page last modified:
Copyright © 1993-2000 prefect - All Rights Reserved.