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

ACIA Serial Driver Code, ACIAserial.c

The following code implements the ACIA serial driver code. It is very similar to SCIserial.c.
/*****************************************************************************
 * DACS : Distributed Audio Control System
 *============================================================================
 *         File: ACIAserial.c
 *       Author: Stephen S. Richardson
 * Date Created: 07.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: ACIAserial.c,v 1.1 1997/07/23 22:12:36 prefect Exp prefect $
 *
 *****************************************************************************/

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

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


/*****************************************************************************
 * ACIA_prep_raw
 *
 * initializes a raw frame
 *****************************************************************************/
void ACIA_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;
}


/*****************************************************************************
 * ACIA_prep_cooked
 *
 * initializes a cooked frame
 *****************************************************************************/
void ACIA_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;
}


/*****************************************************************************
 * ACIA_data_to_cooked
 *
 * stuffs data into a cooked frame, setting parameters, etc.  output frame
 * is suitable to be directly output.
 *****************************************************************************/
void ACIA_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;
}


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

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

  if ( (ACIASTAT&0x10) && (outfr->done==0) ) {

#ifdef _MIXER
    PBC_PC^=0x08;
#endif
    ACIADATA=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 ACIA and unfinished inraw frame? */

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

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

    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
  }
}


/*****************************************************************************
 * ACIA_poll_in
 *
 * polled ACIA input.  returns 1 if there was actually a character to get.
 *****************************************************************************/
int ACIA_poll_in (unsigned char *c)
{
   if (ACIASTAT&0x08) {
      *c=ACIADATA;
      return 1;
   } else {
      return 0;
   }
}


/*****************************************************************************
 * ACIA_block_in
 *
 * blocking ACIA input.  returns character.
 *****************************************************************************/
char ACIA_block_in (void)
{
   while (!(ACIASTAT&0x08));
   return (ACIADATA);
}


/*****************************************************************************
 * ACIA_poll_in
 *
 * polled ACIA input.  returns 1 if there was actually a character to get.
 *****************************************************************************/
void ACIA_chout (unsigned char ch)
{
   while (!(ACIASTAT & 0x10));
   ACIADATA = ch;   
}


/*****************************************************************************
 * ACIA_out
 *
 * ACIA output (blocking)
 *****************************************************************************/
void ACIA_out (char *s)
{
   char *t=s;
   
   while (*t!=0) {
     while (!(ACIASTAT & 0x10));
     ACIADATA = *t++;
   }
}


/*****************************************************************************
 * ACIA_init
 *
 * initialize ACIA port, 9600 baud, 8-N-1
 *****************************************************************************/
void ACIA_init (void)
{
  ACIACTRL = 0x1E;
  ACIACMD = 0xCB;
}


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.