|
Next: TCP/IP Client Library Header,
Up: MIDI Controller
Previous: Serial Communications Header, serial.h
  Contents
This code implements the protocol described in the firmware protocols
section of this design document.
/*****************************************************************************
* DACS : Distributed Audio Control System
*============================================================================
* File: serial.c
* Description: routines to handle serial communications with DACS components
* Author: Stephen S. Richardson
* Date Created: 07.12.97
* Environment: GNU C Compiler (GCC) v2.7.1, Linux i486 v2.0.28
* Build: library
*============================================================================
* 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: serial.c,v 1.1 1997/07/13 14:18:00 prefect Exp prefect $
*
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h>
#include <time.h>
#include <sys/time.h>
#include "serial.h"
void ser_init_frame (struct raw_frame *f)
{
f->len=0;
f->cur=0;
f->done=0;
f->dleflag=0;
f->stxflag=0;
memset (f->data, 0, MAXPAYLOAD);
}
void ser_init_serbuf (struct serbuf *b)
{
b->len=0;
b->len=0;
memset (b->data, 0, SERBUFLEN);
}
int ser_write_buf (struct raw_frame *fr, struct serbuf *ob)
{
int i, j=0;
/* return 0 if the whole frame can't be put in the buffer. */
if (ob->len + fr->len >= SERBUFLEN) return 0;
/* start of frame */
ob->data[j++]=DLE;
ob->data[j++]=STX;
/* data of frame */
for (i=0;i<fr->len;i++) {
if (fr->data[i]==DLE) {
ob->data[j++]=DLE;
ob->data[j++]=DLE; /* character stuffing */
} else {
ob->data[j++]=fr->data[i];
}
}
/* end of frame */
ob->data[j++]=DLE;
ob->data[j++]=ETX;
ob->len+=j;
return (1);
}
int ser_service (struct serbuf *ib, struct serbuf *ob,
struct raw_frame *of, int serfd)
{
int r, i, j;
/* outgoing serial data? */
if (ob->len) {
r=write (serfd, ob->data, ob->len);
if (r<0) {
/* error writing. */
fprintf (stderr, "error writing to serial device.\n");
exit (1);
} else {
/* data were written */
if (r==ob->len) {
/* all data were written */
ob->len=0;
} else {
/* only some of the data were written.. shift buffer left by r */
memmove (ob->data, ob->data+r, ob->len-r);
ob->len -= r;
}
}
}
/* incoming serial data and enough space to store some of it? */
if ((ser_datawaiting (serfd)) && (ib->len < SERBUFLEN)) {
r=read (serfd, ib->data+ib->len, SERBUFLEN - ib->len);
if (r<0) {
fprintf (stderr, "error reading from serial device.\n");
exit (1);
} else {
/* data were read */
ib->len += r;
/* process into a frame */
for (i=0;i<ib->len;i++) {
if (ib->data[i] == DLE) {
/* found a DLE */
if (of->dleflag) {
/* last char was a DLE */
of->dleflag=0;
if (of->stxflag) {
of->data[of->cur++]=DLE; /* it was a character stuffed DLE */
}
} else {
/* last char was not a DLE */
of->dleflag=1;
}
} else {
/* found something other than a DLE */
if (of->dleflag) {
/* last char was a DLE */
of->dleflag=0;
if (ib->data[i] == STX) {
/* found start of packet */
of->stxflag=1;
of->done=0;
of->len=0;
of->cur=0;
} else if (ib->data[i] == ETX) {
/* found end of packet */
of->stxflag=0;
of->len=of->cur;
of->done=1;
}
} else {
/* last character was not DLE */
if (of->stxflag) {
of->data[of->cur++]=ib->data[i]; /* put the data into frame */
}
}
}
}
/* reset input buffer position */
ib->cur=0;
ib->len=0;
}
}
}
int ser_datawaiting (int serfd)
{
fd_set fds;
struct timeval tv;
bzero (&tv, sizeof (struct timeval));
tv.tv_usec = 1;
FD_ZERO (&fds);
FD_SET (serfd, &fds);
while ((select (serfd+1, &fds, NULL, NULL, &tv))==-1); /* make sure select */
/* works */
if (FD_ISSET (serfd, &fds)) return (1);
else return (0);
}
/*****************************************************************************
* ser_open
*
* opens a serial port at a baud rate for NON-BLOCKING read/write
*****************************************************************************/
int ser_open (char *devnam, int bd)
{
struct termios t;
int fd;
/* open device */
fd=open(devnam, O_RDWR|O_NONBLOCK);
if (fd<1) {
fprintf (stderr, "Error opening serial device %s.\n", devnam);
exit (1);
}
tcgetattr (fd, &t);
/* set the port discipline */
t.c_iflag=BRKINT|IGNPAR;
t.c_oflag=OPOST;
t.c_cflag=CS8|CREAD|CLOCAL;
t.c_lflag=0;
cfsetospeed (&t, (speed_t) bd);
cfsetispeed (&t, (speed_t) bd);
tcsetattr (fd, TCSANOW, &t);
return (fd);
}
Steve Richardson
2000-07-06
|
Table of Contents
[Whole document in PDF 1.9MB]
[more photos and information]
|