Difference between revisions of "Arduino loop"

From dftwiki3
Jump to: navigation, search
(arduino-loop.pde)
(arduino-loop.pde)
 
(5 intermediate revisions by the same user not shown)
Line 4: Line 4:
  
 
__TOC__
 
__TOC__
 +
 +
=talkToArduino.asm=
 +
<code><pre>
 +
;;; talkToArduino.asm
 +
;;; D. Thiebaut
 +
;;;
 +
;;;  nasm -f elf talkToArduino.asm
 +
;;;  gcc -o talkToArduino  arduino-serial.c  talkToArduino.o
 +
;;;
 +
 +
;;; ----------------------- EXTERN LABELS -----------------------
 +
extern serialport_writebyte ; int function
 +
extern serialport_write ; int function
 +
extern serialport_read_until ; int function
 +
extern displayBuffer ; int function
 +
 +
extern buf
 +
extern byte
 +
       
 +
        ;; -------------------------
 +
        ;; data segment
 +
        ;; -------------------------
 +
        section .data
 +
msg1 db "w d 13 1", 0
 +
msg1len equ $-msg1
 +
 +
msg2 db "w d 13 0", 0
 +
msg2len equ $-msg2
 +
 +
msg3 db "r d", 0
 +
msg3len equ $-msg3
 +
 +
msg4 db "w d 13 "
 +
msg4val db '?', 0
 +
msg4len equ $-msg4
 +
 +
        section .bss
 +
       
 +
        ;; -------------------------
 +
        ;; code area
 +
        ;; -------------------------
 +
        section .text
 +
        global  asm_main
 +
asm_main:
 +
 +
;; turn Pin 13 On/Off a few times
 +
mov eax, msg1
 +
mov ecx, msg1len
 +
call copyMsg
 +
call serialport_write
 +
 +
call delay100ms
 +
 +
mov eax, msg2
 +
mov ecx, msg2len
 +
call copyMsg
 +
call serialport_write
 +
 +
call delay100ms
 +
 +
mov eax, msg1
 +
mov ecx, msg1len
 +
call copyMsg
 +
call serialport_write
 +
 +
call delay100ms
 +
 +
mov eax, msg2
 +
mov ecx, msg2len
 +
call copyMsg
 +
call serialport_write
 +
 +
.for mov ecx, 1000 ; read/write switch 1000 times
 +
call readPin2 ; get status of Pin 2 in al
 +
call setPin13 ; set Pin 13 to value in al
 +
loop .for
 +
 +
        ;; return to C program
 +
 +
        ret
 +
 +
;;; ----------------------------------------------------------------
 +
;;; copyMsg1: puts array whose address in eax  in external buffer
 +
;;;       number of bytes shoudl be in ecx.
 +
;;; ----------------------------------------------------------------
 +
copyMsg:
 +
pushad
 +
mov esi, eax ; source buffer
 +
mov edi, buf ; destination buffer in C program
 +
.for mov al, [esi]
 +
mov [edi], al
 +
inc esi
 +
inc edi
 +
loop .for
 +
popad
 +
ret
 +
 +
;;; ----------------------------------------------------------------
 +
;;; delay 100 ms.
 +
;;; ----------------------------------------------------------------
 +
delay100ms:
 +
pushad
 +
mov ecx, 100000000 ; 200,000,000 cycles (assuming 2GHz)
 +
.for add eax, 1 ; 1 cycle
 +
loop .for ; 1 cycle
 +
popad
 +
ret
 +
 +
;;; ----------------------------------------------------------------
 +
;;; readPin2: sends the arduino a request for value of pins
 +
;;;            returns '0' or '1' in al as value of Pin 2
 +
;;; ----------------------------------------------------------------
 +
readPin2:
 +
mov eax, msg3
 +
mov ecx, msg3len ; "r d" read digital pins
 +
call copyMsg ; now buf contains "r d"
 +
call serialport_write
 +
 +
call serialport_read_until
 +
;;;  call displayBuffer
 +
 +
;;; get the value of input pin 2 as defined in buffer
 +
;;; which contains "d 0 0 1 0 0 0 1 0 0 0 0 0"
 +
;;; and first 0 is Pin 2, second 0 is Pin 3, etc.
 +
 +
mov al, [buf+2] ; get first digit and put it
 +
                                ; in al
 +
ret
 +
 +
;;; ----------------------------------------------------------------
 +
;;; SetPin13: sets pin 13 to the value '0' or '1' passed in al
 +
;;; ----------------------------------------------------------------
 +
setPin13:
 +
pushad
 +
mov [msg4val],al ; and embed '0' or '1' at right place
 +
mov eax, msg4
 +
mov ecx, msg4len ; copy msg4 in buf
 +
call copyMsg
 +
;;; call    displayBuffer
 +
call serialport_write; send message "w d 13 x" to arduino
 +
popad ; restore registers
 +
 +
ret
 +
 +
</pre></code>
 +
<br />
 +
<br />
 +
<br />
 +
[[Category:CSC231]][[Category:Arduino]]
  
 
=arduino-serial.c=
 
=arduino-serial.c=
Line 14: Line 163:
 
  * A simple command-line example program showing how a computer can
 
  * A simple command-line example program showing how a computer can
 
  * communicate with an Arduino board. Works on any POSIX system (Mac/Unix/PC)  
 
  * communicate with an Arduino board. Works on any POSIX system (Mac/Unix/PC)  
  *
+
  *  
 
  *
 
  *
 
  * Compile with something like:
 
  * Compile with something like:
Line 37: Line 186:
 
  *  Added patch to clean up odd baudrates from Andy at hexapodia.org
 
  *  Added patch to clean up odd baudrates from Andy at hexapodia.org
 
  *
 
  *
 +
* Modified 11/06/08 by D. Thiebaut
 +
*  Force program to wait until a \n is received from Arduino
 +
*  Added linking with assembly program
 
  */
 
  */
  
Line 50: Line 202:
 
#include <getopt.h>
 
#include <getopt.h>
  
 +
extern int asm_main( void );
 +
 +
//-------------------------- prototypes ---------------------------
 
void usage(void);
 
void usage(void);
 
int serialport_init(const char* serialport, int baud);
 
int serialport_init(const char* serialport, int baud);
int serialport_writebyte(int fd, uint8_t b);
+
int serialport_writebyte( );
int serialport_write(int fd, const char* str);
+
int serialport_write( );
int serialport_read_until(int fd, char* buf, char until);
+
int serialport_read_until( );
 +
int displayBuffer( );
 +
 
 +
//---------------------------- globals ----------------------------
 +
int fd = 0;            // file descriptor for USB device
 +
char serialport[256];    // name of the serial port (/dev/ttyUSB0)
 +
int  baudrate = B9600;  // default baud rate
 +
char buf[1024];          // buffer for sent/receive strings
 +
uint8_t byte;
 +
int  pin;
  
 +
//-----------------------------------------------------------------
 +
//-----------------------------------------------------------------
 
void usage(void) {
 
void usage(void) {
 
     printf("Usage: arduino-serial -p <serialport> [OPTIONS]\n"
 
     printf("Usage: arduino-serial -p <serialport> [OPTIONS]\n"
Line 74: Line 240:
 
}
 
}
  
int main(int argc, char *argv[])  
+
//-----------------------------------------------------------------
{
+
int main(int argc, char *argv[]) {
    int fd = 0;
+
     int rc, n;
    char serialport[256];
 
    int baudrate = B9600;  // default
 
    char buf[256];
 
     int rc,n;
 
  
 
     if (argc==1) {
 
     if (argc==1) {
Line 87: Line 249:
 
     }
 
     }
  
     /* parse options */
+
     /*--- parse options ---*/
 
     int option_index = 0, opt;
 
     int option_index = 0, opt;
 
     static struct option loptions[] = {
 
     static struct option loptions[] = {
Line 99: Line 261:
 
     };
 
     };
 
      
 
      
 +
    /*--- process the command line arguments ---*/
 
     while(1) {
 
     while(1) {
         opt = getopt_long (argc, argv, "hp:b:s:rn:d:",
+
         opt = getopt_long ( argc, argv, "hp:b:s:rn:d:",
                           loptions, &option_index);
+
                           loptions, &option_index );
 
         if (opt==-1) break;
 
         if (opt==-1) break;
 
         switch (opt) {
 
         switch (opt) {
Line 117: Line 280:
 
         case 'p':
 
         case 'p':
 
             strcpy(serialport,optarg);
 
             strcpy(serialport,optarg);
             fd = serialport_init(optarg, baudrate);
+
             fd = serialport_init( optarg, baudrate );
 
             if(fd==-1){
 
             if(fd==-1){
 
      printf( "Could not initialize USB port\n\n" );
 
      printf( "Could not initialize USB port\n\n" );
Line 124: Line 287:
 
             break;
 
             break;
 
         case 'n':
 
         case 'n':
             n = strtol(optarg, NULL, 10); // convert string to number
+
             n = strtol(optarg, NULL, 10 ); // convert string to number
             rc = serialport_writebyte(fd, (uint8_t)n);
+
    byte = (uint8_t) n;
 +
             rc = serialport_writebyte( );
 
             if(rc==-1) return -1;
 
             if(rc==-1) return -1;
 
             break;
 
             break;
 
         case 's':
 
         case 's':
             strcpy(buf,optarg);
+
             strcpy( buf, optarg );
             rc = serialport_write(fd, buf);
+
             rc = serialport_write( );
             if(rc==-1) return -1;
+
             if (rc==-1) return -1;
 
             break;
 
             break;
 
         case 'r':
 
         case 'r':
            serialport_read_until(fd, buf, '\n');
+
    serialport_read_until( );
             printf("read: %s\n",buf);
+
             printf("%s\n",buf);
 
             break;
 
             break;
 
         }
 
         }
 
     }
 
     }
  
 +
    //--- call assembly language program ---
 +
    asm_main();
 +
 +
    //--- exit ---
 
     exit(EXIT_SUCCESS);     
 
     exit(EXIT_SUCCESS);     
 +
 
} // end main
 
} // end main
 
      
 
      
int serialport_writebyte( int fd, uint8_t b)
+
//-----------------------------------------------------------------
{
+
//-----------------------------------------------------------------
     int n = write(fd,&b,1);
+
int displayBuffer( ) {
 +
  printf( "buffer = [%s]\n", buf );
 +
  return 0;
 +
}
 +
 
 +
//-----------------------------------------------------------------
 +
//-----------------------------------------------------------------
 +
int serialport_writebyte( ) {
 +
     int n = write( fd, &byte, 1);
 
     if( n!=1)
 
     if( n!=1)
 
         return -1;
 
         return -1;
Line 151: Line 328:
 
}
 
}
  
int serialport_write(int fd, const char* str) {
+
//-----------------------------------------------------------------
 +
//-----------------------------------------------------------------
 +
int serialport_write() {
 
   int len;
 
   int len;
  char buff[1024];
+
   strcat( buf, "\n" );
  strcpy( buff, str );
+
   len = strlen(buf);
   strcat( buff, "\n" );
+
   int n = write( fd, buf, len );
   len = strlen(buff);
+
 
   int n = write(fd, buff, len);
 
 
   if( n!=len )  
 
   if( n!=len )  
 
     return -1;
 
     return -1;
Line 163: Line 341:
 
}
 
}
  
int serialport_read_until(int fd, char* buf, char until) {
+
//-----------------------------------------------------------------
 +
//-----------------------------------------------------------------
 +
int serialport_read_until( ) {
 
     char b[1];
 
     char b[1];
 
     int i=0, k;
 
     int i=0, k;
Line 178: Line 358:
 
buf[i] = b[0];
 
buf[i] = b[0];
 
i++;
 
i++;
     } while( b[0] != until );
+
     } while( b[0] != '\n' );
  
 
     buf[i] = 0;  // null terminate the string
 
     buf[i] = 0;  // null terminate the string
Line 184: Line 364:
 
}
 
}
  
 +
//-----------------------------------------------------------------
 
// takes the string name of the serial port (e.g. "/dev/tty.usbserial","COM1")
 
// 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.
 
// 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.
 
// opens the port in fully raw mode so you can send binary data.
 
// returns valid fd, or -1 on error
 
// returns valid fd, or -1 on error
 +
//-----------------------------------------------------------------
 
int serialport_init(const char* serialport, int baud)
 
int serialport_init(const char* serialport, int baud)
 
{
 
{
Line 210: Line 392:
 
     case 4800:  brate=B4800;  break;
 
     case 4800:  brate=B4800;  break;
 
     case 9600:  brate=B9600;  break;
 
     case 9600:  brate=B9600;  break;
#ifdef B14400
+
    #ifdef B14400
 
     case 14400:  brate=B14400;  break;
 
     case 14400:  brate=B14400;  break;
#endif
+
    #endif
 
     case 19200:  brate=B19200;  break;
 
     case 19200:  brate=B19200;  break;
#ifdef B28800
+
    #ifdef B28800
 
     case 28800:  brate=B28800;  break;
 
     case 28800:  brate=B28800;  break;
#endif
+
    #endif
 
     case 38400:  brate=B38400;  break;
 
     case 38400:  brate=B38400;  break;
 
     case 57600:  brate=B57600;  break;
 
     case 57600:  brate=B57600;  break;
Line 229: Line 411:
 
     toptions.c_cflag &= ~CSIZE;
 
     toptions.c_cflag &= ~CSIZE;
 
     toptions.c_cflag |= CS8;
 
     toptions.c_cflag |= CS8;
 +
 
     // no flow control
 
     // no flow control
 
     toptions.c_cflag &= ~CRTSCTS;
 
     toptions.c_cflag &= ~CRTSCTS;
Line 249: Line 432:
 
     return fd;
 
     return fd;
 
}
 
}
 
  
  
Line 257: Line 439:
  
 
<code><pre>
 
<code><pre>
 
+
//
// ===================================================
 
 
// arduino-loop.pde
 
// arduino-loop.pde
// D. Thiebaut
 
 
// 11/6/08
 
// 11/6/08
// Similar to the simpleMessageSystem, but uses
+
// V. 5
//  no library. Listens to the USB port for commands
 
//  of the type "w d 13 1" (write 1 to digital pin 13)
 
//  or of the type "r d" (read digital pins)
 
// Sends the string "OK\n" after processing a command
 
//  whether it is processed successfully or not. 
 
// ===================================================
 
  
 
// -------------------------------------------------------------
 
// -------------------------------------------------------------
Line 322: Line 496:
 
  Serial.println( "Error" );
 
  Serial.println( "Error" );
 
}
 
}
        Serial.println( "OK" );
 
 
         resetAll();
 
         resetAll();
 
         return;
 
         return;
Line 432: Line 605:
 
     if ( mode=='a' )
 
     if ( mode=='a' )
 
         analogWrite( intPin, intState );
 
         analogWrite( intPin, intState );
 +
    //delay( 50 ); // 0.05 sec
 +
    //Serial.println( "OK" );
 
     return 0;
 
     return 0;
 
}
 
}
Line 458: Line 633:
 
   return 0;
 
   return 0;
 
}
 
}
 +
  
  
  
 
</pre></code>
 
</pre></code>
 +
<br />
 +
 +
<br />
 +
 +
<br />
 +
 +
<br />
 +
 +
<br />
 +
 +
<br />
 +
[[Category:CSC231]][[Category:Arduino]][[Category:C]]

Latest revision as of 12:39, 9 October 2010

--D. Thiebaut 17:08, 1 November 2008 (UTC)

Status: could make arduino-serial.c program send commands and read from Arduino

talkToArduino.asm

;;; talkToArduino.asm
;;; D. Thiebaut
;;; 
;;;  nasm -f elf talkToArduino.asm
;;;  gcc -o talkToArduino  arduino-serial.c  talkToArduino.o
;;;

;;; ----------------------- EXTERN LABELS -----------------------
extern serialport_writebyte	; int function
extern serialport_write		; int function
extern serialport_read_until	; int function
extern displayBuffer		; int function
	
extern buf	
extern byte		
        
        ;; -------------------------
        ;; data segment
        ;; -------------------------
        section .data
msg1	db	"w d 13 1", 0
msg1len	equ	$-msg1
	
msg2	db	"w d 13 0", 0
msg2len equ	$-msg2

msg3	db	"r d", 0
msg3len	equ	$-msg3

msg4	db	"w d 13 "
msg4val	db	'?', 0
msg4len	equ	$-msg4
	
        section .bss
        
        ;; -------------------------
        ;; code area
        ;; -------------------------
        section .text
        global  asm_main
asm_main:
	
	;; turn Pin 13 On/Off a few times
	mov	eax, msg1
	mov	ecx, msg1len
	call	copyMsg
	call	serialport_write

	call	delay100ms
	
	mov	eax, msg2
	mov	ecx, msg2len
	call	copyMsg
	call	serialport_write	
	
	call	delay100ms
		
	mov	eax, msg1
	mov	ecx, msg1len
	call	copyMsg
	call	serialport_write
	
	call	delay100ms
	
	mov	eax, msg2
	mov	ecx, msg2len
	call	copyMsg
	call	serialport_write	

.for	mov	ecx, 1000	; read/write switch 1000 times
	call	readPin2	; get status of Pin 2 in al
	call	setPin13	; set Pin 13 to value in al
	loop	.for
	
        ;; return to C program
	
        ret

;;; ----------------------------------------------------------------
;;; copyMsg1: puts array whose address in eax  in external buffer
;;; 	      number of bytes shoudl be in ecx.
;;; ----------------------------------------------------------------
copyMsg:
	pushad
	mov	esi, eax	; source buffer
	mov	edi, buf	; destination buffer in C program
.for	mov	al, [esi]
	mov	[edi], al
	inc	esi
	inc	edi
	loop	.for
	popad
	ret
	
;;; ----------------------------------------------------------------
;;; delay 100 ms.
;;; ----------------------------------------------------------------
delay100ms:
	pushad
	mov	ecx, 100000000	; 200,000,000 cycles (assuming 2GHz)
.for	add	eax, 1		; 1 cycle
	loop	.for		; 1 cycle
	popad
	ret

;;; ----------------------------------------------------------------
;;; readPin2: sends the arduino a request for value of pins
;;;             returns '0' or '1' in al as value of Pin 2
;;; ----------------------------------------------------------------
readPin2:	
	mov	eax, msg3
	mov	ecx, msg3len	; "r d" read digital pins
	call	copyMsg		; now buf contains "r d"
	call	serialport_write
	
	call	serialport_read_until
;;;   	call	displayBuffer

;;; get the value of input pin 2 as defined in buffer
;;; which contains "d 0 0 1 0 0 0 1 0 0 0 0 0"
;;; and first 0 is Pin 2, second 0 is Pin 3, etc.
	
	mov	al, [buf+2]	; get first digit and put it
                                ; in al 
	ret

;;; ----------------------------------------------------------------
;;; SetPin13: sets pin 13 to the value '0' or '1' passed in al
;;; ----------------------------------------------------------------
setPin13:
	pushad
	mov	[msg4val],al	; and embed '0' or '1' at right place
	mov	eax, msg4
	mov	ecx, msg4len	; copy msg4 in buf
	call	copyMsg
;;; 	call    displayBuffer
	call	serialport_write; send message "w d 13 x" to arduino
	popad			; restore registers

	ret




arduino-serial.c


/*
 * Arduino-serial
 * --------------
 * 
 * A simple command-line example program showing how a computer can
 * communicate with an Arduino board. Works on any POSIX system (Mac/Unix/PC) 
 * 
 *
 * Compile with something like:
 * gcc -o arduino-serial arduino-serial.c
 *
 * Created 5 December 2006
 * Copyleft (c) 2006, Tod E. Kurt, tod@todbot.com
 * http://todbot.com/blog/
 *
 * 
 * Updated 8 December 2006: 
 *  Justin McBride discoevered B14400 & B28800 aren't in Linux's termios.h.
 *  I've included his patch, but commented out for now.  One really needs a
 *  real make system when doing cross-platform C and I wanted to avoid that
 *  for this little program. Those baudrates aren't used much anyway. :)
 *
 * Updated 26 December 2007:
 *  Added ability to specify a delay (so you can wait for Arduino Diecimila)
 *  Added ability to send a binary byte number
 *
 * Update 31 August 2008:
 *  Added patch to clean up odd baudrates from Andy at hexapodia.org
 *
 * Modified 11/06/08 by D. Thiebaut
 *  Force program to wait until a \n is received from Arduino
 *  Added linking with assembly program
 */

#include <stdio.h>    /* Standard input/output definitions */
#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>

extern int asm_main( void );

//-------------------------- prototypes ---------------------------
void usage(void);
int serialport_init(const char* serialport, int baud);
int serialport_writebyte( );
int serialport_write( );
int serialport_read_until( );
int displayBuffer( );

//---------------------------- globals ----------------------------
int  fd = 0;             // file descriptor for USB device
char serialport[256];    // name of the serial port (/dev/ttyUSB0)
int  baudrate = B9600;   // default baud rate
char buf[1024];          // buffer for sent/receive strings
uint8_t byte;
int  pin;

//-----------------------------------------------------------------
//-----------------------------------------------------------------
void usage(void) {
    printf("Usage: arduino-serial -p <serialport> [OPTIONS]\n"
    "\n"
    "Options:\n"
    "  -h, --help                   Print this help message\n"
    "  -p, --port=serialport        Serial port Arduino is on\n"
    "  -b, --baud=baudrate          Baudrate (bps) of Arduino\n"
    "  -s, --send=data              Send data to Arduino\n"
    "  -r, --receive                Receive data from Arduino & print it out\n"
    "  -n  --num=num                Send a number as a single byte\n"
    "  -d  --delay=millis           Delay for specified milliseconds\n"
    "\n"
    "Note: Order is important. Set '-b' before doing '-p'. \n"
    "      Used to make series of actions:  '-d 2000 -s hello -d 100 -r' \n"
    "      means 'wait 2secs, send 'hello', wait 100msec, get reply'\n"
    "\n");
}

//-----------------------------------------------------------------
int main(int argc, char *argv[]) {
    int rc, n;

    if (argc==1) {
        usage();
        exit(EXIT_SUCCESS);
    }

    /*--- parse options ---*/
    int option_index = 0, opt;
    static struct option loptions[] = {
        {"help",       no_argument,       0, 'h'},
        {"port",       required_argument, 0, 'p'},
        {"baud",       required_argument, 0, 'b'},
        {"send",       required_argument, 0, 's'},
        {"receive",    no_argument,       0, 'r'},
        {"num",        required_argument, 0, 'n'},
        {"delay",      required_argument, 0, 'd'}
    };
    
    /*--- process the command line arguments ---*/
    while(1) {
        opt = getopt_long ( argc, argv, "hp:b:s:rn:d:",
                           loptions, &option_index );
        if (opt==-1) break;
        switch (opt) {
        case '0': break;
        case 'd':
            n = strtol(optarg,NULL,10);
            usleep(n * 1000 ); // sleep milliseconds
            break;
        case 'h':
            usage();
            break;
        case 'b':
            baudrate = strtol(optarg,NULL,10);
            break;
        case 'p':
            strcpy(serialport,optarg);
            fd = serialport_init( optarg, baudrate );
            if(fd==-1){
	      printf( "Could not initialize USB port\n\n" );
	      return -1;
	    }
            break;
        case 'n':
            n = strtol(optarg, NULL, 10 ); // convert string to number
	    byte = (uint8_t) n;
            rc = serialport_writebyte( );
            if(rc==-1) return -1;
            break;
        case 's':
            strcpy( buf, optarg );
            rc = serialport_write( );
            if (rc==-1) return -1;
            break;
        case 'r':
	    serialport_read_until( );
            printf("%s\n",buf);
            break;
        }
    }

    //--- call assembly language program ---
    asm_main();

    //--- exit ---
    exit(EXIT_SUCCESS);    

} // end main
    
//-----------------------------------------------------------------
//-----------------------------------------------------------------
int displayBuffer( ) {
  printf( "buffer = [%s]\n", buf );
  return 0;
}

//-----------------------------------------------------------------
//-----------------------------------------------------------------
int serialport_writebyte( ) {
    int n = write( fd, &byte, 1);
    if( n!=1)
        return -1;
    return 0;
}

//-----------------------------------------------------------------
//-----------------------------------------------------------------
int serialport_write() {
  int len;
  strcat( buf, "\n" );
  len = strlen(buf);
  int n = write( fd, buf, len );

  if( n!=len ) 
    return -1;
  return 0;
}

//-----------------------------------------------------------------
//-----------------------------------------------------------------
int serialport_read_until( ) {
    char b[1];
    int i=0, k;
    do { 
        int n = read(fd, b, 1);  // read a char at a time
        if( n==-1) {
	  usleep( 100*1000 );
	  continue;
	}
        if( n==0 ) {
            usleep( 10 * 1000 ); // wait 10 msec try again
            continue;
        }
	buf[i] = b[0];
	i++;
    } while( b[0] != '\n' );

    buf[i] = 0;  // null terminate the string
    return 0;
}

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


arduino-loop.pde

 //
// arduino-loop.pde
// 11/6/08
// V. 5

// -------------------------------------------------------------
// GLOBALS
// -------------------------------------------------------------
char buffer[256];
int len;
char *operation;
char *mode;
char *pin;
char *state;

// -------------------------------------------------------------
// PROTOTYPES
// -------------------------------------------------------------
void resetAll();
int process();
int writePin( char mode, int pin, int state );
int readPins( char mode );

// -------------------------------------------------------------
// SETUP: initializes port and buffer
// -------------------------------------------------------------
void setup() {
    Serial.begin(9600); 
    resetAll();
}

// -------------------------------------------------------------
// RESETALL: clears the buffer and the globals
// -------------------------------------------------------------
void resetAll() {
    buffer[0] = '\0';
    len       = 0;
    operation = mode = pin = state = 0;
}

// -------------------------------------------------------------
// LOOP: main workhorse.  Called repeatedly.  Gets chars from 
//       the arduino, and processes it when \n received
// -------------------------------------------------------------
void loop() {

    int c;
    c = Serial.read();

    // nothing received, nothing to do
    if (c==-1) return;
    
    // \n terminator received, process message
    if ( c=='\n' ) {
        if ( process() ) {
	   Serial.println( "Error" );
	}
        resetAll();
        return;
    }
         
    // something received, but not \n. add to buffer
    buffer[ len++ ] = c;
    buffer[ len ] = '\0';
}

// -------------------------------------------------------------
// MYSTRTOK: equivalent to C strtok function that doesn't seem
//           supported by arduino.  Given a pointer to a string
//           p, returns a pointer q past p that points to a char
//           that is not a space.  If cannot find one, return
//           NULL.
// -------------------------------------------------------------
char* mystrtok( char* p, int skipNonBlank ) {
    char* q=p;
    if ( skipNonBlank ) {
        for ( ; *q != ' ' && *q != '\0'; q++ );
        if ( *q=='\0' ) return NULL;
    }
    for ( ; *q != '\0' && *q==' '; q++ );
    if ( *q == '\0' ) return NULL;
    if ( *q == ' ' ) return NULL;
    return q;
}

// -------------------------------------------------------------
// PROCESS: if we're here it's because we have received a message
//          from the UBUNTU PC.
// -------------------------------------------------------------
int process() {
    char *p;
    int len = strlen( buffer );
    int intPin;
    int intState;

    //Serial.print( "buffer = " );
    //Serial.print( buffer );
    
    //--- if message less than 3 chars long, return ---
    if ( len < 3 ) {
        resetAll();
        return 1; //error
    }

    //--- get the operation: 'w' or 'r'.  Do some error checking---
    operation = mystrtok( buffer, 0 );

    if ( ( !operation || (*operation!='r' && *operation!='w') ) 
         || ( ( *operation=='r' && len < 3 ) ||( *operation=='w' && len < 7 ) ) ) {
        resetAll();
        return 1; // error
    }

    //--- get the mode: 'd' or 'a' and do some error checking ---
    mode = mystrtok( operation + 1, 0 );
    if (  !mode || ( *mode!='a' && *mode!='d' ) ) {
        resetAll();
        return 1; // success
    }

    //--- if operation is 'r' read the pins ---
    if ( *operation == 'r' ) {
        readPins( *mode );
        resetAll();
        return 0; // success
    }

    //--- if not, operation is 'w', then get pin # and state ---
    pin = mystrtok( mode + 1, 0 );
    if ( !pin ) {
        resetAll();
        return 1; // error
    }
    intPin = atoi( pin );
    if ( intPin < 2 || intPin > 13 ) {
        resetAll();
        return 1; // error
    }
    
    //--- get the state of the output pin ---
    state = mystrtok( pin+1, 1 );
    if ( !state ) {
        resetAll();
        return 1; // error 
    }
    intState = atoi( state );
    if ( intState < 0 || intState > 1 ) {
        resetAll();
        return 1; // error
    }
    
    //--- write the state to the pin in question ---
    writePin( *mode, intPin, intState );

    resetAll();
    return 0;
}

// -------------------------------------------------------------
// WRITEPIN: depending on mode, writes the state to the pin
// -------------------------------------------------------------
int writePin( char mode, int  intPin, int intState ) {
    if ( mode=='d' )
        digitalWrite( intPin, intState );
    if ( mode=='a' )
        analogWrite( intPin, intState );
    //delay( 50 ); // 0.05 sec
    //Serial.println( "OK" );
    return 0;
}

// -------------------------------------------------------------
// READPINS: read the status of all the pins and returns it as
//      a string.
// -------------------------------------------------------------
int readPins( char mode ) {
  int i;
  if ( mode=='d' ) {
        Serial.print( "d " );
        for ( i=2; i<14; i++ ) {
            Serial.print( digitalRead( i ) );
            Serial.print( ' ' );
        }
  }
  if ( mode=='a' ) {
        Serial.print( "a " );
        for ( i=0; i<6; i++ ) {
            Serial.print( analogRead( i ) );
            Serial.print( ' ' );
        }
  }
  Serial.println();
  return 0;
}