gnupic: Wisp628 Xwisp2 Linux support


Previous by date: 25 Aug 2005 06:32:52 +0100 Re: [gnupic] [PIC] Pickit 2 firmware available from the shipped C D, Chen Xiao Fan
Next by date: 25 Aug 2005 06:32:52 +0100 Re: [gnupic] Wisp628 Xwisp2 Linux support, Rob Hamerling
Previous in thread:
Next in thread: 25 Aug 2005 06:32:52 +0100 Re: Wisp628 Xwisp2 Linux support, Herman Aalderink

Subject: Wisp628 Xwisp2 Linux support
From: Chen Xiao Fan ####@####.####
Date: 25 Aug 2005 06:32:52 +0100
Message-Id: <3B8AEFFADD3DD4118F8100508BACEC2C0A2890D1@spex>

Thanks for releasing the new versions of XWisp2. It supports
quite a lot of PICs (PIC16F and PIC18F) including the 18F USB
parts. I should say it is just great! It is much faster than
the Python based Xwisp and supports much more chips. Adding
the Linux support will be even greater. :)

Regarding the Linux support, I do not know much about Linux 
programming. Still maybe you can take a look at the serial code 
part of LPLAB (across Linux and Windows).

LPLAB is at http://www.landamore.com/pic.html.

A fork of LPLAB is called Piclab by Nicolas at http://piclab.sf.net.

Regards,
Xiaofan

-------From Nicolas----------------------------------------
"It uses LPLAB code and can program with via the serial port... 
It might work better than LPLAB.

Writing with LPLAB regularly failed for me as it was trying to use the
fast mode (apparently serial ports on Linux cannot be configured
properly for high speed mode)."

Nicolas
-------End of quote from Nicolas' post to PICList--------

--------LPLAB serial code--------------------------------
/*
 * lplab - linux replacement for mplab
 *
 * (c) 2002-2003 Stephen Landamore ####@####.####
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#ifndef _SERIAL_H
#define _SERIAL_H

enum {
    SERIAL_NONE,
    SERIAL_PICSTART_PLUS,
    SERIAL_ICD, SERIAL_ICD2,
    SERIAL_PROMATE2
};

void serial_debug( int debug );
int serial_init( const char *serial_dev, int what, int baud );
int serial_set_speed( int baud );
void serial_close( void );
void serial_setflowcontrol( int on );
int serial_getcts( void );
void serial_setdtr( int on );
void serial_setrts( int on );
void serial_send( const unsigned char *buf, int len );
int serial_getc( void );
int serial_receive( unsigned char *buf, int len );
void serial_flush( void );
const char **serial_list( void );

#endif /* _SERIAL_H */

/*
 * Local Variables:
 * c-basic-offset: 4
 * End:
 */

/*
 * lplab - linux replacement for mplab
 *
 * (c) 2002-2003 Stephen Landamore ####@####.####
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "serial.h"

/* ----------------------------------------------------------------------
 * the debug code is common to all arch's
 * -------------------------------------------------------------------- */
static int sdebug = 0;
static int serial_what = SERIAL_NONE;

void
serial_debug( int debug )
{
    sdebug = debug;
}

static void
debug_log( const unsigned char *buf, int len )
{
    static FILE *log = NULL;
    if ( log == NULL ) {
	if ( (log=fopen("serial.log","w")) == NULL ) {
	    perror( "serial.log" );
	    exit( 1 );
	}
    }
    fwrite( buf, len, 1, log );
    fflush( log );
}

static void
debug_dump( char *which, const unsigned char *buf, int len )
{
    int i, col=20;
    if ( sdebug == 2 ) {
	debug_log( buf, len );
	return;
    }
    if ( ! sdebug ) return;
    printf("%s: %d,\042", which, len);
    for (i=0; i<len; i++) {
	int c = *(buf+i);
	if ( c>=32 && c<=126 ) {
	    putchar(c);
	    col++;
	} else {
	    switch( c ) {
	    case '\r': printf("\\r"); col+=2; break;
	    case '\n': printf("\\n"); col+=2; break;
	    default: printf("\\x%02x",c); col+=4; break;
	    }
	}
	if ( col>70 ) { printf("..."); break; }
    }
    printf("\042\n");
}

#if defined(linux)

/* ----------------------------------------------------------------------
 * linux specific code
 * -------------------------------------------------------------------- */

#include <string.h>
#include <errno.h>
#include <termio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>

static int serial = -1;
static struct termios initinfo;
static struct termios info;

static int
get_speed( int baud )
{
    switch( baud ) {
    case   9600: return B9600;
    case  19200: return B19200;
    case  38400: return B38400;
    case  57600: return B57600;
    case 115200: return B115200;
    }
    return 0;
}

int
serial_init( const char *serial_dev, int what, int baud )
{
    int speed = get_speed( baud );
    assert( serial_dev );
    if ( speed == 0 ) {
	printf( "invalid baud rate" );
	return -1;
    }
    if ( serial != -1 ) serial_close();
    if ( (serial=open(serial_dev,O_NDELAY|O_RDWR|O_NOCTTY)) == -1 ) {
	perror( "serial: open failed" );
	return -1;
    }
    if ( tcgetattr(serial,&initinfo) == -1 ) {
	perror( "serial: tcgetattr1 failed" );
	return -1;
    }
    tcflush( serial, TCIOFLUSH );
    if ( tcgetattr(serial,&info) == -1 ) {
	perror( "serial: tcgetattr2 failed" );
	return -1;
    }
    serial_what = what;
    switch( what ) {
    case SERIAL_NONE:
	printf( "serial.c: init(SERIAL_NONE)!\n" );
	exit( 1 );
	break;
    case SERIAL_PICSTART_PLUS:
	// always runs at 19200, 8n1
	cfsetispeed(&info,speed);
	cfsetospeed(&info,speed);
	// 8 data bits
	info.c_cflag &= ~CSIZE;
	info.c_cflag |= CS8;
	info.c_iflag &= ~ISTRIP;
	// no parity
	info.c_cflag &= ~(PARENB|PARODD);
	info.c_iflag &= ~INPCK;
	// 1 stop bit
	info.c_cflag &= ~CSTOPB;
	// raw access to serial port (uncooked)
	info.c_iflag &= ~(IGNCR|INLCR|ICRNL|IXOFF|IXON);
	info.c_oflag &= ~OPOST;
	info.c_cflag &= ~HUPCL;
	info.c_cflag |= (CLOCAL|CREAD);
	info.c_lflag &= ~(ICANON|ECHO|ECHONL|ISIG|IEXTEN|TOSTOP);
	info.c_cc[VINTR]  = _POSIX_VDISABLE;
	info.c_cc[VQUIT]  = _POSIX_VDISABLE;
	info.c_cc[VSUSP]  = _POSIX_VDISABLE;
	info.c_cc[VSTART] = _POSIX_VDISABLE;
	info.c_cc[VSTOP]  = _POSIX_VDISABLE;
	// misc stuff
	info.c_cc[VMIN]   = 0; // wait for 1 char or timeout
	info.c_cc[VTIME]  = 0; // wait this long, then fail
	break;
    case SERIAL_ICD:
	// always runs at 57600, 8n1
	cfsetispeed(&info,speed);
	cfsetospeed(&info,speed);
	// 8 data bits
	info.c_cflag &= ~CSIZE;
	info.c_cflag |= CS8;
	info.c_iflag &= ~ISTRIP;
	// no parity
	info.c_cflag &= ~(PARENB|PARODD);
	info.c_iflag &= ~INPCK;
	// 1 stop bit
	info.c_cflag &= ~CSTOPB;
	// raw access to serial port (uncooked)
	info.c_iflag &= ~(IGNCR|INLCR|ICRNL|IXOFF|IXON);
	info.c_oflag &= ~OPOST;
	info.c_cflag &= ~HUPCL;
	info.c_cflag |= (CLOCAL|CREAD);
	info.c_lflag &= ~(ICANON|ECHO|ECHONL|ISIG|IEXTEN|TOSTOP);
	// misc stuff
	info.c_cc[VMIN]  = 0; // wait for 1 char or timeout
	info.c_cc[VTIME] = 0; // wait this long, then fail
	break;
    case SERIAL_ICD2:
	// always runs at 57600, 8n1
	cfsetispeed(&info,speed);
	cfsetospeed(&info,speed);
	// 8 data bits
	info.c_cflag &= ~CSIZE;
	info.c_cflag |= CS8;
	info.c_iflag &= ~ISTRIP;
	// no parity
	info.c_cflag &= ~(PARENB|PARODD);
	info.c_iflag &= ~INPCK;
	// 1 stop bit
	info.c_cflag &= ~CSTOPB;
	// raw access to serial port (uncooked)
	info.c_iflag &= ~(IGNCR|INLCR|ICRNL|IXOFF|IXON);
	info.c_oflag &= ~OPOST;
	info.c_cflag &= ~HUPCL;
	info.c_cflag |= (CLOCAL|CREAD);
	info.c_lflag &= ~(ICANON|ECHO|ECHONL|ISIG|IEXTEN|TOSTOP);
	// misc stuff
	info.c_cc[VMIN]  = 0; // wait for 1 char or timeout
	info.c_cc[VTIME] = 0; // wait this long, then fail
	break;
    case SERIAL_PROMATE2:
	// always runs at 19200, 8n1
	cfsetispeed(&info,speed);
	cfsetospeed(&info,speed);
	// 8 data bits
	info.c_cflag &= ~CSIZE;
	info.c_cflag |= CS8;
	info.c_iflag &= ~ISTRIP;
	// no parity
	info.c_cflag &= ~(PARENB|PARODD);
	info.c_iflag &= ~INPCK;
	// 1 stop bit
	info.c_cflag &= ~CSTOPB;
	// raw access to serial port (uncooked)
	info.c_iflag &= ~(IGNCR|INLCR|ICRNL|IXOFF|IXON);
	info.c_oflag &= ~OPOST;
	info.c_cflag &= ~HUPCL;
	info.c_cflag |= (CLOCAL|CREAD);
	info.c_lflag &= ~(ICANON|ECHO|ECHONL|ISIG|IEXTEN|TOSTOP);
	info.c_cc[VINTR]  = _POSIX_VDISABLE;
	info.c_cc[VQUIT]  = _POSIX_VDISABLE;
	info.c_cc[VSUSP]  = _POSIX_VDISABLE;
	info.c_cc[VSTART] = _POSIX_VDISABLE;
	info.c_cc[VSTOP]  = _POSIX_VDISABLE;
	// misc stuff
	info.c_cc[VMIN]   = 0; // wait for 1 char or timeout
	info.c_cc[VTIME]  = 0; // wait this long, then fail
	break;
    default:
	printf( "device %d not yet supported\n", what );
	exit( 1 );
	break;
    }
    if ( tcsetattr(serial,TCSANOW,&info) == -1 ) {
	perror( "serial: tcsetattr failed" );
	return -1;
    }
    //fcntl( serial, F_SETFL, 0 ); // BLOCKING
    return 0;
}

int
serial_set_speed( int baud )
{
    int speed = get_speed( baud );
    assert( serial != -1 );
    tcdrain( serial );
    tcflush( serial, TCIOFLUSH );
    cfsetispeed(&info,speed);
    cfsetospeed(&info,speed);
    if ( tcsetattr(serial,TCSANOW,&info) == -1 ) {
	perror( "serial_set_speed: tcsetattr failed" );
	return -1;
    }
    return 0;
}

void
serial_close( void )
{
    serial_flush();
    if ( serial != -1 ) {
	tcsetattr( serial, TCSANOW, &initinfo );
	close( serial );
    }
    serial = -1;
}

void
serial_setflowcontrol( int on )
{
    assert( serial >= 0 );
    if ( on ) {
	info.c_cflag |= CRTSCTS;
    } else {
	info.c_cflag &= ~CRTSCTS;
    }
    info.c_cc[VMIN]  = 0;
    info.c_cc[VTIME] = 0;
    if ( tcsetattr(serial,TCSANOW,&info) == -1 ) {
	perror( "serial: tcsetattr failed" );
	exit( 1 );
    }
}

int
serial_getcts( void )
{
    int status;
    assert( serial >= 0 );
    if ( ioctl(serial,TIOCMGET,&status) == -1 ) {
	perror( "ioctl TIOCMGET failed" );
	exit( 1 );
    }
    if ( status & TIOCM_CTS )
	return 1;
    else
	return 0;
}

void
serial_setdtr( int on )
{
    int control = TIOCM_DTR;
    assert( serial >= 0 );
    if ( on ) {
	ioctl(serial,TIOCMBIS,&control);
    } else {
	ioctl(serial,TIOCMBIC,&control);
    }
}

void
serial_setrts( int on )
{
    int control = TIOCM_RTS;
    assert( serial >= 0 );
    if ( on ) {
	ioctl(serial,TIOCMBIS,&control);
    } else {
	ioctl(serial,TIOCMBIC,&control);
    }
}

static int
serial_select( void )
{
    int ret;
    struct pollfd pfd[2];
    if ( serial == -1 ) return -1;
    pfd[0].fd = serial;
    pfd[0].events = POLLIN;
    pfd[1].fd = fileno(stdin);
    pfd[1].events = POLLIN;
    for (;;) {
	ret = poll( pfd, 2, -1 ); // wait forever on these two fds
	if ( ret == -1 ) {
	    if ( errno == EINTR || errno == EAGAIN ) continue;
	    return -1;
	}
	break;
    }
    if ( pfd[1].revents ) {
	//printf( "keyboard ready!\n" );
	return -2;
    }
    if ( pfd[0].revents )
	return 0;
    return -1;
}

void
serial_send( const unsigned char *buf, int len )
{
    if ( serial == -1 ) return;
    debug_dump( "send", buf, len );
    while( len ) {
	int ww = write( serial, buf, len );
	if ( ww == -1 ) {
	    if ( errno == EINTR || errno == EAGAIN ) continue;
	    perror( "serial: write failed" );
	    exit( 1 );
	}
	buf += ww;
	len -= ww;
    }
    switch( serial_what ) {
    case SERIAL_PICSTART_PLUS:
	//case SERIAL_PROMATE2:
    case SERIAL_ICD:
	// SL - commented out for speedier picstart+ on 24Jan03
	// SL - commented out for speedier icd on 20Apr03
	// SL - can't do same with icd2 (well, not with hardware flow
control)
	break;
    default: 
	tcdrain( serial );
	break;
    }
}

int
serial_getc( void )
{
    static unsigned char buf[32];
    static int buflen = 0;
    static int bufptr = 0;
    assert( serial >= 0 );
    if ( buflen == bufptr ) {
	// read more stuff into buffer
	int sel = serial_select();
	if ( sel < 0 ) {
	    printf( "serial_getc: select returned %d\n", sel );
	    return sel;
	}
	buflen = read( serial, buf, 32 );
	bufptr = 0;
	if ( buflen == -1 ) {
	    buflen = 0;
	    if ( errno == EINTR || errno == EAGAIN )
		return -1;
	    perror( "serial: read failed" );
	    exit( 1 );
	}
	debug_dump( "recv", buf, buflen );
    }
    return buf[ bufptr++ ];
}

int
serial_receive( unsigned char *buf, int len )
{
    int i, c;
    for (i=0; i<len; i++) {
	c = serial_getc();
	if ( c == -1 ) break;
	buf[i] = c;
    }
    return i;
}

void
serial_flush( void )
{
    if ( serial == -1 ) return;
    tcdrain( serial );
    tcflush( serial, TCIFLUSH );
}

const char **
serial_list( void )
{
    static const char *list[] = {
	"/dev/ttyS0",
	"/dev/ttyS1",
	"/dev/ttyS2",
	"/dev/ttyS3",
	NULL
    };
    return list;
}

/* end of linux code */

#else

/* ----------------------------------------------------------------------
 * windows specific code
 * -------------------------------------------------------------------- */

#include <wtypes.h>
#include <winbase.h>

static HANDLE serial = NULL;

int
serial_init( const char *serial_dev, int what, int baud )
{
    struct _DCB CommSettings;
    struct _COMMTIMEOUTS CommTimeouts;

    if ( serial != NULL ) serial_close();
    serial_what = what;
    serial = CreateFile( serial_dev, GENERIC_READ|GENERIC_WRITE,
			 0, NULL, OPEN_EXISTING, 0, NULL );
    if ( serial == NULL )
	return -1;
    GetCommState( serial, &CommSettings ); /* read current port setup */
    CommSettings.BaudRate = baud;
    CommSettings.fBinary = TRUE;
    CommSettings.fParity = FALSE;
    CommSettings.fOutxCtsFlow = FALSE;
    CommSettings.fOutxDsrFlow = FALSE;
    CommSettings.fDtrControl = DTR_CONTROL_ENABLE;
    CommSettings.fDsrSensitivity = FALSE;
    CommSettings.fTXContinueOnXoff = TRUE;
    CommSettings.fOutX = FALSE;
    CommSettings.fInX = FALSE;
    CommSettings.fErrorChar = FALSE;
    CommSettings.fNull = FALSE;
    CommSettings.fRtsControl = RTS_CONTROL_ENABLE;
    CommSettings.fAbortOnError = FALSE;
    CommSettings.ByteSize = 8;
    CommSettings.Parity = NOPARITY;
    CommSettings.StopBits = ONESTOPBIT;

    if ( SetCommState(serial,&CommSettings) == 0 )
	return -1;

    CommTimeouts.ReadIntervalTimeout = 0;
    CommTimeouts.ReadTotalTimeoutMultiplier = 0;
    CommTimeouts.ReadTotalTimeoutConstant = 20;
    CommTimeouts.WriteTotalTimeoutMultiplier = 0;
    CommTimeouts.WriteTotalTimeoutConstant = 0;
    SetCommTimeouts( serial, &CommTimeouts );

    return 0;
}

int
serial_set_speed( int baud )
{
    struct _DCB CommSettings;
    // get current comm settings
    if ( GetCommState(serial,&CommSettings) == 0 )
	return -1;
    // set baud rate
    CommSettings.BaudRate = baud;
    if ( SetCommState(serial,&CommSettings) == 0 )
	return -1;
    return 0;
}

void
serial_close( void )
{
    serial_flush();
    if ( serial != NULL )
	CloseHandle( serial );
    serial = NULL;
}

void
serial_setflowcontrol( int on )
{
    struct _DCB CommSettings;
    GetCommState( serial, &CommSettings ); // read current serial settings
    if ( on )
	CommSettings.fOutxCtsFlow = TRUE;
    else
	CommSettings.fOutxCtsFlow = FALSE;
    SetCommState( serial, &CommSettings );
}

int
serial_getcts( void )
{
    DWORD errors;
    COMSTAT stat;
    // FIXME: not sure about this!
    ClearCommError( serial, &errors, &stat );
    if ( stat.fCtsHold )
	return 0;
    else
	return 1;
}

void
serial_setdtr( int on )
{
    if ( on )
	EscapeCommFunction( serial, SETDTR );
    else
	EscapeCommFunction( serial, CLRDTR );
}

void
serial_setrts( int on )
{
    if ( on )
	EscapeCommFunction( serial, SETRTS );
    else
	EscapeCommFunction( serial, CLRRTS );
}

void
serial_send( const unsigned char *buf, int len )
{
    unsigned long ww;
    if ( serial == NULL ) return;
    debug_dump( "send", buf, len );
    WriteFile( serial, buf, len, (DWORD *)&ww, NULL );
    FlushFileBuffers( serial );
    Sleep( 10 );
}

int
serial_getc( void )
{
    static unsigned char buf[32];
    static int buflen = 0;
    static int bufptr = 0;
    while( buflen == bufptr ) {
	// read more stuff into buffer
	DWORD rr = 0;
	ReadFile( serial, buf, 32, &rr, NULL ); // 20msec timeout
	buflen = rr;
	bufptr = 0;
	debug_dump( "recv", buf, buflen );
    }
    // finally there is something in the buffer
    return buf[ bufptr++ ];
}

int
serial_receive( unsigned char *buf, int len )
{
    int i, c;
    for (i=0; i<len; i++) {
	c = serial_getc();
	if ( c == -1 ) break;
	buf[i] = c;
    }
    return i;
}

void
serial_flush( void )
{
    if ( serial == NULL ) return;
    FlushFileBuffers( serial );
    PurgeComm( serial, PURGE_RXCLEAR );
}

const char **
serial_list( void )
{
    static const char *list[] = {
	"COM1",
	"COM2",
	"COM3",
	"COM4",
	NULL
    };
    return list;
}

/* end of win32 code */

#endif

/*
 * Local Variables:
 * c-basic-offset: 4
 * End:
 */

-----Original Message-----
From: Rob Hamerling ####@####.####
Sent: Monday, August 15, 2005 6:11 PM
To: ####@####.####
Subject: Re: [gnupic] Learning PIC on the job

Chen Xiao Fan wrote:
> Wisp628 is a much better recomendation for programmers under 
> both Linux and Windows than JDM/Tait type. It is a pity that 
> so far XWisp2 (the C port of XWisp under OS/2 and Windows 
> from Rob Hamerling http://www.robh.nl) does not work
> with Linux yet. Only the python program is working under
> Linux and it is much slower than XWisp2. It seems to me
> that only the os dependent xwisp2os.c needs to be ported
> to Linux. Maybe some expert in this list can take a
> look at it.


Thank you Xiaofan! I've tried myself several times, and I got some
positive reactions but no code yet!
BTW I've just released a new version of Xwisp2!

Regards, Rob.

-- 
Rob Hamerling, Vianen, NL phone +31-347-322822
homepage: http://www.robh.nl/

Previous by date: 25 Aug 2005 06:32:52 +0100 Re: [gnupic] [PIC] Pickit 2 firmware available from the shipped C D, Chen Xiao Fan
Next by date: 25 Aug 2005 06:32:52 +0100 Re: [gnupic] Wisp628 Xwisp2 Linux support, Rob Hamerling
Previous in thread:
Next in thread: 25 Aug 2005 06:32:52 +0100 Re: Wisp628 Xwisp2 Linux support, Herman Aalderink


Powered by ezmlm-browse 0.20.