⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rcxsend.c

📁 RCXDownload and RCXDirectMode是leJOS的一个可视化接口。RCXDownload自动设置JDK-, leJOS-和ClassPath
💻 C
📖 第 1 页 / 共 2 页
字号:
/**
 * rcxsend.c
 * This is essentially a copy of Jose Solorzanos tvm_firmdl3.c or 
 * rather Kekoa Proudfoot's firmdl3.c and send.c, available 
 * at     http://graphics.stanford.edu/~kekoa/rcx/firmdl3.c
 * and    http://graphics.stanford.edu/~kekoa/rcx/tools.html
 * License information shown below.
 * 
 * Tim's changes:
 *   05/30/01 -- This file replaces the old RCXPort-implementation,
 *               which was based on the javax.comm-Driver.
 *               It extends the compatibility of send.c with Cygwin
 *               on Windows 9x Systems.
 *               Added some command line options, like -debug, -tty.
 *               Suppressed complements.
 *               Removed fast mode.
 */
/*
 *  send.c
 *
 *  A program to communicate with an RCX.
 *
 *  Copyright (C) 1998, Kekoa Proudfoot.  All Rights Reserved.
 */
/*
 *  firmdl3.c
 *
 *  A firmware downloader for the RCX.  Version 3.0.  Supports single and
 *  quad speed downloading.
 *
 *  The contents of this file are subject to the Mozilla Public License
 *  Version 1.0 (the "License"); you may not use this file except in
 *  compliance with the License. You may obtain a copy of the License at
 *  http://www.mozilla.org/MPL/
 *
 *  Software distributed under the License is distributed on an "AS IS"
 *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 *  License for the specific language governing rights and limitations
 *  under the License.
 *
 *  The Original Code is Firmdl code, released October 3, 1998.
 *
 *  The Initial Developer of the Original Code is Kekoa Proudfoot.
 *  Portions created by Kekoa Proudfoot are Copyright (C) 1998, 1999
 *  Kekoa Proudfoot. All Rights Reserved.
 *
 *  Contributor(s): Kekoa Proudfoot <kekoa@graphics.stanford.edu>
 *                  Laurent Demailly
 *                  Allen Martin
 *                  Markus Noga
 *                  Gavin Smyth
 *                  Luis Villa
 *                  Jose Solorzano
 */


/*
 *  usage: rcxsend [options] byte [byte ...] (e.g. rcxsend --debug 10)
 *
 *  If necessary, set DEFAULTTTY, below, to the serial device you want to use.
 *  Set the RCXTTY environment variable to override DEFAULTTTY.
 *  Use the command-line option --tty=TTY to override RCXTTY and DEFAULTTTY.
 *
 *  Tim Rinkens
 *  tau@uni-paderborn.de
 *  05/30/01
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <ctype.h>
#include <string.h>
/* #include "util.h" */

#if defined(_WIN32)
  #include <windows.h>
#endif


/* Machine-dependent defines */

#if defined(LINUX) || defined(linux)
#define DEFAULTTTY   "/dev/ttyS0" /* Linux - COM1 */
#elif defined (_WIN32)
#define DEFAULTTTY   "com1"       /* Cygwin - COM1 */
#elif defined (sun)
#define DEFAULTTTY   "/dev/ttya"  /* Solaris - first serial port - untested */
#else
#define DEFAULTTTY   "/dev/ttyd2" /* IRIX - second serial port */
#endif

/* Global variables */

char *progname;


/*** rcx_comm.h ***/

#ifndef RCX_COMM_H_INCLUDED
#define RCX_COMM_H_INCLUDED

#define RCX_OK             0
#define RCX_NO_TOWER      -1
#define RCX_BAD_LINK      -2
#define RCX_BAD_ECHO      -3
#define RCX_NO_RESPONSE   -4
#define RCX_BAD_RESPONSE  -5

#if defined(_WIN32)
  #define FILEDESCR	HANDLE
  #define BADFILE	NULL
#else
  #define FILEDESCR	int
  #define BADFILE	-1
#endif


/* Get a file descriptor for the named tty, exits with message on error */
// extern FILEDESCR rcx_init (char *tty, int is_fast);
extern FILEDESCR rcx_init (char *tty);

/* Close a file descriptor allocated by rcx_init */
extern void rcx_close (FILEDESCR fd);

/* Try to wakeup the tower for timeout ms, returns error code */
extern int rcx_wakeup_tower (FILEDESCR fd, int timeout);

/* Try to send a message, returns error code */
/* Set use_comp=1 to send complements, use_comp=0 to suppress them */
// extern int rcx_send (FILEDESCR fd, void *buf, int len, int use_comp);
extern int rcx_send (FILEDESCR fd, void *buf, int len);

/* Try to receive a message, returns error code */
/* Set use_comp=1 to expect complements */
/* Waits for timeout ms before detecting end of response */
// extern int rcx_recv (FILEDESCR fd, void *buf, int maxlen, int timeout, int use_comp);
extern int rcx_recv (FILEDESCR fd, void *buf, int maxlen, int timeout);

/* Try to send a message and receive its response, returns error code */
/* Set use_comp=1 to send and receive complements, use_comp=0 otherwise */
/* Waits for timeout ms before detecting end of response */
// extern int rcx_sendrecv (FILEDESCR fd, void *send, int slen, void *recv, int rlen, int timeout, int retries, int use_comp);
extern int rcx_sendrecv (FILEDESCR fd, void *send, int slen, void *recv, int rlen, int timeout, int retries);

/* Test whether or not the rcx is alive, returns 1=yes, 0=no */
/* Set use_comp=1 to send complements, use_comp=0 to suppress them */
// extern int rcx_is_alive (FILEDESCR fd, int use_comp);
extern int rcx_is_alive (FILEDESCR fd);

/* Convert an error code to a string */
extern char *rcx_strerror(int error);

/* Hexdump routine */
extern void hexdump(char *prefix, void *buf, int len);


#endif /* RCX_COMM_H_INCLUDED */

/*** rcx_comm.c ***/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <sys/time.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

#if defined(_WIN32)
  #include <windows.h>
#endif

/* Defines */

#define BUFFERSIZE  4096

/* Globals */

int __comm_debug = 0;

/* Timer routines */

typedef struct timeval timeval_t;

#define tvupdate(tv)  gettimeofday(tv,NULL)
#define tvsec(tv)     ((tv)->tv_sec)
#define tvmsec(tv)    ((tv)->tv_usec * 1e-3)

static float
timer_reset(timeval_t *timer)
{
    tvupdate(timer);
    return 0;
}

static float
timer_read(timeval_t *timer)
{
    timeval_t now;
    tvupdate(&now);
    return tvsec(&now) - tvsec(timer) + (tvmsec(&now) - tvmsec(timer)) * 1e-3;
}

void myperror(char *str) {
#if defined(_WIN32)
    fprintf(stderr, "Error %lu: %s\n", (unsigned long) GetLastError(), str);
#else
    perror(str);
#endif
}

/* Timeout read routine */

static int nbread (FILEDESCR fd, void *buf, int maxlen, int timeout)
{
    char *bufp = (char *)buf;
    int len = 0;

    while (len < maxlen) {

#if defined(_WIN32)
	DWORD count;
	COMMTIMEOUTS CommTimeouts;

	GetCommTimeouts (fd, &CommTimeouts);

        // Change the COMMTIMEOUTS structure settings.
        CommTimeouts.ReadIntervalTimeout = MAXDWORD;
        CommTimeouts.ReadTotalTimeoutMultiplier = 0;
        CommTimeouts.ReadTotalTimeoutConstant = timeout;
        CommTimeouts.WriteTotalTimeoutMultiplier = 10;
        CommTimeouts.WriteTotalTimeoutConstant = 1000;

        // Set the time-out parameters for all read and write operations
        // on the port.
        SetCommTimeouts(fd, &CommTimeouts);

        if (ReadFile(fd, &bufp[len], maxlen - len, &count, NULL) == FALSE) {
            myperror("ReadFile");
	    fprintf(stderr, "nb_read - error reading tty: %lu\n", (unsigned long) GetLastError());
	    exit(1);
	}

        len += count;

        if (count == 0) {
            //timeout
	    break;
        }
#else
	int count;
	fd_set fds;
	struct timeval tv;

	FD_ZERO(&fds);
	FD_SET(fd, &fds);

	tv.tv_sec = timeout / 1000;
	tv.tv_usec = (timeout % 1000) * 1000;

	if (select(fd+1, &fds, NULL, NULL, &tv) < 0) {
	    perror("select");
	    exit(1);
	}

	if (!FD_ISSET(fd, &fds))
	    break;

	if ((count = read(fd, &bufp[len], maxlen - len)) < 0) {
	    perror("read");
	    exit(1);
	}

        len += count;
#endif

    }

    return len;
}

/* discard all characters in the input queue of tty */
static void rx_flush(FILEDESCR fd)
{
#if defined(_WIN32)
    PurgeComm(fd, PURGE_RXABORT | PURGE_RXCLEAR);
#else
    char echo[BUFFERSIZE];
    nbread(fd, echo, BUFFERSIZE, 200);
#endif
}

int mywrite(FILEDESCR fd, const void *buf, size_t len) {
#if defined(_WIN32)
    DWORD nBytesWritten=0;
    WriteFile(fd, buf, len, &nBytesWritten, NULL);
    return nBytesWritten;
#else
    return write(fd, buf, len);
#endif
}

/* RCX routines */

FILEDESCR rcx_init(char *tty) // , int is_fast)
{
    FILEDESCR fd;

#if defined(_WIN32)
    DCB dcb;
#else
    struct termios ios;
#endif

    // if (__comm_debug) printf("mode = %s\n", is_fast ? "fast" : "slow");
	if (__comm_debug) printf("mode = %s\n", "slow");

#if defined(_WIN32)
    if ((fd = CreateFile(tty, GENERIC_READ | GENERIC_WRITE,
                              0, NULL, OPEN_EXISTING,
                              0, NULL)) == INVALID_HANDLE_VALUE) {
	fprintf(stderr, "Error %lu: Opening %s\n", (unsigned long) GetLastError(), tty);
	exit(1);
    }

    // Serial settings
    FillMemory(&dcb, sizeof(dcb), 0);
    if (!GetCommState(fd, &dcb)) {	// get current DCB
        // Error in GetCommState
	myperror("GetCommState");
        exit(1);
    } else {
	dcb.ByteSize = 8;
	// dcb.Parity   = (is_fast ? 0 : 1);
	dcb.Parity   = (1);	        // 0-4=no,odd,even,mark,space
	dcb.StopBits = 0;			// 0,1,2 = 1, 1.5, 2
	dcb.fBinary  = TRUE ;
	// dcb.fParity  = (is_fast ? FALSE : TRUE) ;
	dcb.fParity  = (TRUE) ;
	dcb.fAbortOnError = FALSE ;
	// dcb.BaudRate = (is_fast ? CBR_4800 : CBR_2400);
	dcb.BaudRate = (CBR_2400);	// Update DCB rate.

	// Set new state.
	if (!SetCommState(fd, &dcb)) {
	    // Error in SetCommState. Possibly a problem with the communications
            // port handle or a problem with the DCB structure itself.
	    myperror("SetCommState");
	    exit(1);
        }

    }

#else

    if ((fd = open(tty, O_RDWR)) < 0) {
	perror(tty);
	exit(1);
    }

    if (!isatty(fd)) {
	close(fd);
	fprintf(stderr, "%s: not a tty\n", tty);
	exit(1);
    }

    memset(&ios, 0, sizeof(ios));
/*
    if (is_fast) {
	ios.c_cflag = CREAD | CLOCAL | CS8;
	cfsetispeed(&ios, B4800);
	cfsetospeed(&ios, B4800);
    }
    else {
*/
	ios.c_cflag = CREAD | CLOCAL | CS8 | PARENB | PARODD;
	cfsetispeed(&ios, B2400);
	cfsetospeed(&ios, B2400);
//    }

    if (tcsetattr(fd, TCSANOW, &ios) == -1) {
	perror("tcsetattr");
	exit(1);
    }
#endif

    return fd;
}

void rcx_close(FILEDESCR fd)
{
#if defined(_WIN32)
    CloseHandle(fd);
#else
    close(fd);
#endif
}

int rcx_wakeup_tower (FILEDESCR fd, int timeout)
{
    char msg[] = { 0x10, 0xfe, 0x10, 0xfe };
    char keepalive = 0xff;
    char buf[BUFFERSIZE];
    timeval_t timer;
    int count = 0;
    int len;

    // First, I send a KeepAlive Byte to settle IR Tower...
    mywrite(fd, &keepalive, 1);
    usleep(20000);
    rx_flush(fd);

    timer_reset(&timer);

    do {
	if (__comm_debug) {
	    printf("writelen = %d\n", sizeof(msg));
	    hexdump("W", msg, sizeof(msg));
	}
	if (mywrite(fd, msg, sizeof(msg)) != sizeof(msg)) {
	    myperror("write");
	    exit(1);
	}
	count += len = nbread(fd, buf, BUFFERSIZE, 50);
	if (len == sizeof(msg) && !memcmp(buf, msg, sizeof(msg)))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -