Logo Search packages:      
Sourcecode: csound version File versions  Download package

serial.c
#include <stdlib.h> 
#include <stdint.h>   /* Standard types */
#include <string.h>   /* String function definitions */
#include <unistd.h>   /* UNIX standard function definitions */
#include <fcntl.h>    /* File control definitions */
#include <errno.h>    /* Error number definitions */
#include <termios.h>  /* POSIX terminal control definitions */
#include <sys/ioctl.h>
#include <getopt.h>

#include "csdl.h"
#include "csound.h"

/*****************************************************
 
                  CSOUND SERIAL PORT OPCODES
                    ma++ ingalls, 2011/9/4
 
 * based on "Arduino-serial"
 * Copyleft (c) 2006, Tod E. Kurt, tod@todbot.com
 * http://todbot.com/blog/
 

open a port.  baudRate defaults to 9600
      iPort  serialBegin         SPortName [, baudRate ]
 
close a port
                  serialEnd           iPort

write byte(s) to the port, at i or k rate
                  serialWrite_i       iPort, iByte
                  serialWrite_i       iPort, kByte
                  serialWrite_i       iPort, Sbytes
                  serialWrite         iPort, iByte
                  serialWrite         iPort, kByte
                  serialWrite         iPort, Sbytes

read the next byte from the input buffer
returned value will be in the range of 0-255
      kByte serialRead          iPort
    
print to screen any bytes (up to 32k) in input buffer
note that these bytes will be cleared from the buffer.
use this opcode mainly for debugging messages.
if you want to mix debugging and other communication 
messages over the same port, you will need to manually
parse the data with the serialRead opcode.
                  serialPrint             iPort
 
clear the input buffer
                  serialFlush         iPort

 
TODO: (might need some kind of threaded buffer-read?)
 
 kNum   serialAvailable    iPort
 returns number of bytes available to read
 
 kByte   serialPeekByte      iPort
 returns the next byte in the input buffer
 does not remove the byte from the buffer
 
*****************************************************/

00065 typedef struct {
    OPDS  h;
    MYFLT *returnedPort, *portName, *baudRate;
} SERIALBEGIN;
int serialBegin(CSOUND *csound, SERIALBEGIN *p);

00071 typedef struct {
    OPDS  h;
    MYFLT *port;
} SERIALEND;
int serialEnd(CSOUND *csound, SERIALEND *p);

00077 typedef struct {
    OPDS  h;
    MYFLT *port, *toWrite;
} SERIALWRITE;
int serialWrite(CSOUND *csound, SERIALWRITE *p);

00083 typedef struct {
    OPDS  h;
    MYFLT *rChar, *port;
} SERIALREAD;
int serialRead(CSOUND *csound, SERIALREAD *p);

00089 typedef struct {
    OPDS  h;
    MYFLT *port;
} SERIALPRINT;
int serialPrint(CSOUND *csound, SERIALPRINT *p);

00095 typedef struct {
    OPDS  h;
    MYFLT *port;
} SERIALFLUSH;
int serialFlush(CSOUND *csound, SERIALFLUSH *p);


///-----------TODO
00103 typedef struct {
    OPDS  h;
    MYFLT *retVal, *port;
} SERIALAVAIL;
int serialAvailable(CSOUND *csound, SERIALAVAIL *p);

00109 typedef struct {
    OPDS  h;
    MYFLT *retChar, *port;
} SERIALPEEK;
int serialPeekByte(CSOUND *csound, SERIALPEEK *p);
//------------------


// takes the string name of the serial port (e.g. "/dev/tty.usbserial","COM1")
// and a baud rate (bps) and connects to that port at that speed and 8N1.
// opens the port in fully raw mode so you can send binary data.
// returns valid fd, or -1 on error
int serialport_init(const char* serialport, int baud)
{
    struct termios toptions;
    int fd;
    
    fprintf(stderr,"init_serialport: opening port %s @ %d bps\n",
            serialport,baud);
      
    fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1)  {
      perror("init_serialport: Unable to open port ");
      return -1;
    }
    
    if (tcgetattr(fd, &toptions) < 0) {
      perror("init_serialport: Couldn't get term attributes");
      return -1;
    }
    //speed_t brate = baud; // let you override switch below if needed
    speed_t brate = B9600;  // ma++ changed to always default to 9600
    switch(baud) {
    case 4800:   brate=B4800;   break;
    case 9600:   brate=B9600;   break;
#ifdef B14400
    case 14400:  brate=B14400;  break;
#endif
    case 19200:  brate=B19200;  break;
#ifdef B28800
    case 28800:  brate=B28800;  break;
#endif
    case 38400:  brate=B38400;  break;
    case 57600:  brate=B57600;  break;
    case 115200: brate=B115200; break;
    }
    cfsetispeed(&toptions, brate);
    cfsetospeed(&toptions, brate);
      
    // 8N1
    toptions.c_cflag &= ~PARENB;
    toptions.c_cflag &= ~CSTOPB;
    toptions.c_cflag &= ~CSIZE;
    toptions.c_cflag |= CS8;
    // no flow control
    toptions.c_cflag &= ~CRTSCTS;
      
    toptions.c_cflag |= CREAD | CLOCAL;  // turn on READ & ignore ctrl lines
    toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
      
    toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
    toptions.c_oflag &= ~OPOST; // make raw
      
    // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
    toptions.c_cc[VMIN]  = 0;
    toptions.c_cc[VTIME] = 20;
    
    if ( tcsetattr(fd, TCSANOW, &toptions) < 0) {
      perror("init_serialport: Couldn't set term attributes");
      return -1;
    }
      
    return fd;
}

int serialBegin(CSOUND *csound, SERIALBEGIN *p)
{
    *p->returnedPort = serialport_init((char *)p->portName, *p->baudRate);
    return OK;
}
int serialEnd(CSOUND *csound, SERIALEND *p)
{
    close(*p->port);
    return OK;
}
int serialWrite(CSOUND *csound, SERIALWRITE *p)
{
    if (p->XSTRCODE & 2)
      write(*p->port, p->toWrite, strlen((char *)p->toWrite));
    else {
      unsigned char b = *p->toWrite;
      write(*p->port, &b, 1);
    }

    return OK;
}

int serialRead(CSOUND *csound, SERIALREAD *p)
{
    unsigned char b = 0;
    ssize_t bytes = read(*p->port, &b, 1);
    if (bytes > 0)
      *p->rChar = b;
    else 
      *p->rChar = -1;
    
    return OK;
}

int serialPrint(CSOUND *csound, SERIALPRINT *p)
{
    char str[32768];
    ssize_t bytes = read(*p->port, str, 32768);
    if (bytes > 0) {
      str[bytes] = 0; // terminate
      csound->MessageS(csound, CSOUNDMSG_ORCH, "%s", str);
    }
    return OK;
}

int serialFlush(CSOUND *csound, SERIALFLUSH *p)
{
    tcflush(*p->port, TCIFLUSH); // who knows if this works...
    return OK;
}

int serialAvailable(CSOUND *csound, SERIALAVAIL *p)
{
    //TODO
    return OK;
}
int serialPeekByte(CSOUND *csound, SERIALPEEK *p)
{
    //TODO
    return OK;
}



#define S(x)    sizeof(x)

static OENTRY localops[] = {
    { (char *)"serialBegin", S(SERIALBEGIN), 1, (char *)"i", (char *)"So",
      (SUBR)serialBegin, (SUBR)NULL, (SUBR)NULL   },
    { (char *)"serialEnd", S(SERIALEND), 2, (char *)"", (char *)"i",
      (SUBR)NULL, (SUBR)serialEnd, (SUBR)NULL   },
    { (char *)"serialWrite_i", S(SERIALWRITE), 1, (char *)"", (char *)"iT",
      (SUBR)serialWrite, (SUBR)NULL, (SUBR)NULL   },
    { (char *)"serialWrite", S(SERIALWRITE), 2, (char *)"", (char *)"iU",
      (SUBR)NULL, (SUBR)serialWrite, (SUBR)NULL   },
    { (char *)"serialRead", S(SERIALREAD), 2, (char *)"k", (char *)"i",
      (SUBR)NULL, (SUBR)serialRead, (SUBR)NULL   },
    { (char *)"serialPrint", S(SERIALPRINT), 2, (char *)"", (char *)"i",
      (SUBR)NULL, (SUBR)serialPrint, (SUBR)NULL   },
    { (char *)"serialFlush", S(SERIALFLUSH), 2, (char *)"", (char *)"i",
      (SUBR)NULL, (SUBR)serialFlush, (SUBR)NULL   },
    { (char *)"serialAvailable", S(SERIALAVAIL), 2, (char *)"k", (char *)"i",
      (SUBR)NULL, (SUBR)serialAvailable, (SUBR)NULL   },
    { (char *)"serialPeekByte", S(SERIALPEEK), 2, (char *)"k", (char *)"i",
      (SUBR)NULL, (SUBR)serialPeekByte, (SUBR)NULL   }
};

Generated by  Doxygen 1.6.0   Back to index