Device-LaCrosse-WS23xx

 view release on metacpan or  search on metacpan

WS23xx.xs  view on Meta::CPAN

    if (read_device(fh, readdata, byte_count+1) != byte_count+1) {
#ifdef DEBUG
	fprintf(stderr,"read_data:read_device(3)\n");
#endif
	return -1;
    }

    if (readdata[byte_count] != data_checksum(readdata, byte_count)) {
#ifdef DEBUG
	fprintf(stderr,"read_data:data_checksum(1)\n");
#endif
	return -1;
    }

    // Success
    return byte_count;
}



int
read_safe(int fh, ushort address, ushort byte_count, uchar *buf)
{
    int i;

    for (i=0; i < 10; i++) {
	// If we get the expected number of bytes, we're done.
	if (read_data(fh, address, byte_count, buf) == byte_count)
	    return 1;

	// FIXME: warn?  Reset?
//	_ws_reset(fh);
	trace("**",0,0," read_data failed");
	tcflush(fh, TCIOFLUSH);
    }

    return 0;
}




MODULE = Device::LaCrosse::WS23xx	PACKAGE = Device::LaCrosse::WS23xx

void
_ws_trace_path(path)
	char *     path
CODE:
	trace_path = malloc(strlen(path));
	if (trace_path == 0)
	    croak("malloc failed");
	strcpy(trace_path,path);

int
_ws_open(path)
	char *     path
    INIT:
	int fh;
	struct termios adtio;
	int portstatus, fdflags;
    PPCODE:
	//Setup serial port
	if ((fh = open(path, O_RDWR | O_NONBLOCK | O_SYNC)) < 0)
	{
//	    fprintf(stderr,"\nUnable to open serial device %s\n", path);
	    XSRETURN_UNDEF;
	}

	if ( flock(fh, LOCK_EX|LOCK_NB) < 0 ) {
	    fprintf(stderr,"Serial device is locked by other program\n");
	    close(fh);
	    XSRETURN_UNDEF;
	}

	if ((fdflags = fcntl(fh, F_GETFL)) == -1 ||
	     fcntl(fh, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
	{
		perror("couldn't reset non-blocking mode");
		exit(EXIT_FAILURE);
	}

	tcgetattr(fh, &adtio);

	// Serial control options
	adtio.c_cflag &= ~PARENB;      // No parity
	adtio.c_cflag &= ~CSTOPB;      // One stop bit
	adtio.c_cflag &= ~CSIZE;       // Character size mask
	adtio.c_cflag |= CS8;          // Character size 8 bits
	adtio.c_cflag |= CREAD;        // Enable Receiver
	adtio.c_cflag &= ~HUPCL;       // No "hangup"
	adtio.c_cflag &= ~CRTSCTS;     // No flowcontrol
	adtio.c_cflag |= CLOCAL;       // Ignore modem control lines

	// Baudrate, for newer systems
	cfsetispeed(&adtio, B2400);
	cfsetospeed(&adtio, B2400);

	// Serial local options: adtio.c_lflag
	// Raw input = clear ICANON, ECHO, ECHOE, and ISIG
	// Disable misc other local features = clear FLUSHO, NOFLSH, TOSTOP, PENDIN, and IEXTEN
	// So we actually clear all flags in adtio.c_lflag
	adtio.c_lflag = 0;

	// Serial input options: adtio.c_iflag
	// Disable parity check = clear INPCK, PARMRK, and ISTRIP
	// Disable software flow control = clear IXON, IXOFF, and IXANY
	// Disable any translation of CR and LF = clear INLCR, IGNCR, and ICRNL
	// Ignore break condition on input = set IGNBRK
	// Ignore parity errors just in case = set IGNPAR;
	// So we can clear all flags except IGNBRK and IGNPAR
	adtio.c_iflag = IGNBRK|IGNPAR;

	// Serial output options
	// Raw output should disable all other output options
	adtio.c_oflag &= ~OPOST;

	adtio.c_cc[VTIME] = 10;		// timer 1s
	adtio.c_cc[VMIN] = 0;		// blocking read until 1 char

	if (tcsetattr(fh, TCSANOW, &adtio) < 0)
	{
//	    fprintf(stderr,"Unable to initialize serial device");
	    XSRETURN_UNDEF;
	}

	tcflush(fh, TCIOFLUSH);

	// Set DTR low and RTS high and leave other ctrl lines untouched
	ioctl(fh, TIOCMGET, &portstatus);	// get current port status
	portstatus &= ~TIOCM_DTR;
	portstatus |= TIOCM_RTS;
	ioctl(fh, TIOCMSET, &portstatus);	// set current port status

	// Reset the device, just once
	_ws_reset(fh);

	// Return the filehandle as a perl scalar
	XPUSHs(sv_2mortal(newSVnv(fh)));

int
_ws_close(fh)
	int	fh
CODE:
	flock(fh, LOCK_UN);
	RETVAL = close(fh);

void
_ws_read(fh, addr, nybble_count)
	int fh
	unsigned short addr
	unsigned char nybble_count
    PREINIT:
	uchar buf[40];
    PPCODE:
#if	DEBUG
	printf("got here: fh=%d addr=%04X nybbles=%d\n",fh,addr,nybble_count);
#endif
	if (read_safe(fh, addr, (nybble_count+1)/2, buf)) {
	    int i;

	    for (i=0; i < nybble_count; i += 2) {
		XPUSHs(sv_2mortal(newSVnv(buf[i/2] & 0x0F)));
		if (i < nybble_count-1)
		    XPUSHs(sv_2mortal(newSVnv(buf[i/2] >> 4)));
	    }
	}
	else {
	    croak("read_safe failed");
	}



( run in 0.728 second using v1.01-cache-2.11-cpan-5511b514fd6 )