diff options
28 files changed, 5809 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e647ae1 --- /dev/null +++ b/Makefile @@ -0,0 +1,72 @@ +# $Id: Makefile,v 1.5 2008/05/21 20:22:44 mr_brain Exp $ +# +# Simple makefile for the libk8055 library +# +# change this to your distribution default +# usually /usr/local or /usr +PREFIX = ?/usr/local +CC = gcc +EXEC = k8055 +VERSION =0.4.1 +BINDIR = $(PREFIX)/bin +LIBDIR = $(PREFIX)/lib +PYLIBDIR = pyk8055 +INCLUDEDIR = $(PREFIX)/include +MANDIR = $(PREFIX)/man/man1 +OBJS = main.o libk8055.o +CFLAGS = -O2 -DDAEMON -DVERSION='"$(VERSION)"' -Wall +LIBS = -lusb -L/usr/lib -lm +LINK = ln + +libk8055.so.$(VERSION): libk8055.o + $(CC) -o libk8055.so.${VERSION} $(LIBS) -shared libk8055.o + -$(LINK) -sf libk8055.so.${VERSION} libk8055.so + +libk8055.o: libk8055.c + $(CC) $(CFLAGS) -c -g -fPIC libk8055.c + +libk8055.a: libk8055.o + ar rvs libk8055.a libk8055.o + +libk8055.c: k8055.h + +all: k8055_prog libk8055.so.${VERSION} libk8055.a + +.PHONY: k8055_prog + +k8055_prog: $(OBJS) + $(CC) $(OBJS) -o $(EXEC) $(LIBS) + # strip $(EXEC) + +pylib: $(PYLIBDIR)/libk8055.i libk8055.c + export VERSION=$(VERSION); $(MAKE) -C $(PYLIBDIR) + +clean: + rm -f *.o libk8055.so libk8055.so.$(VERSION) $(EXEC) libk8055.a + @$(MAKE) -C $(PYLIBDIR) clean + +install: k8055_prog libk8055.so.$(VERSION) + cp -f $(EXEC) $(BINDIR)/ + if !(test -d $(LIBDIR)); then \ + mkdir -p $(LIBDIR); \ + fi + if !(test -d $(INCLUDEDIR)); then \ + mkdir -p $(INCLUDEDIR); \ + fi + rm -f $(LIBDIR)/libk8055* + cp -Pf lib* $(LIBDIR) + cp -f k8055.h $(INCLUDEDIR) + if !(test -d $(MANDIR)); then \ + mkdir -p $(MANDIR); \ + fi + cp -f man/k8055.1.gz $(MANDIR)/ + +pyinstall: $(PYLIBDIR)/libk8055.i + @$(MAKE) -C $(PYLIBDIR) install + +uninstall: + rm -f $(BINDIR)/$(EXEC) $(LIBDIR)/libk8055* $(INCLUDEDIR)/k8055.h + +test: k8055_prog + -@killall $(EXEC) + ./$(EXEC) diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..5b5d45c --- /dev/null +++ b/README.txt @@ -0,0 +1,37 @@ +The k8055 require libusb-0.1.9 or newer and kernel 2.4.18 or never. + +install: + # make all + # make install + update ld.so.conf with "/usr/local/lib" if not there or run + env-update at gentoo systems + +uninstall: + # make uninstall + +Check out the Makefile for all different make rules... + +User access to the k8055 device: + read comments in velleman.rules + +Using the k8055 library: + in the program file "#include <k8055.h>" and compile with -lk8055 and + -lusb, e.g gcc -lusb -lk8055 main.c -o k8055_rocks + +Python part + Python makes use of SWIG interface language, for setup and install + see http://www.swig.org + + There might be a prepared package for your distribution, use + emerge swig, apt-get install swig, urpmi swig, rpm -Uvh swig_package + Or whatever your favorite distribution provides. + Then, from the library source directory: + + # make pylib + + You can then run the python programs from within the pyk8055 directory + + For global install, run as root: + # make pyinstall + This should install your package in the proper site-package dircetory + globally accessible for the python interpreter diff --git a/java/build.xml b/java/build.xml new file mode 100644 index 0000000..66dc02c --- /dev/null +++ b/java/build.xml @@ -0,0 +1,213 @@ +<?xml version="1.0"?> +<!-- + * Copyright (C) 2008 Martin Pischky (mailto:martin@pischky.de) + * + * This file (build.xml) is part of libk8055/jk8055. + * jk8055 - a java wrapper for libk8055 + * + * + * libk8055/jk8055 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * $Id: build.xml,v 1.4 2008/07/28 09:58:30 pischky Exp $ +--> +<project name="jk8055" default="all"> + <description> + java wrapper for libk8055 + </description> + + <property environment="env" /> + + <!-- some files --> + + <property name="file.base" value="jk8055" /> + <property name="file.c" location="src/c/${file.base}.c" /> + + <property name="version" value="0.3" /> + + <!-- set global properties for building --> + + <property file="build.properties" /> + <property file="${user.home}/build.properties" /> + <!-- example (build.properties is not stored in cvs): + # My installation of M$ VS 2003. + # Use VS 2003 Command Prompt to get the value + VSINSTALLDIR=D:\\Programme\\Visual Studio .NET 2003\\Common7\\IDE + VCINSTALLDIR=D:\\Programme\\Microsoft Visual Studio .NET 2003 + # My installation of the java development kit + jdk.home=D:\\j2sdk1.4.2_11 + # My installation of the Velleman "K8055D_C.lib", "K8055D_C.DLL", + # "K8055D_C.h" and "K8055D.DLL" + VellemanDir=D:\\Programme\\Velleman\\K8055 + --> + + <!-- set properties if not definded in build.properties --> + + <!-- guess java development kit --> + <property name="jdk.home" value="${env.JDK_HOME}" /> + + <!-- guess c compiler for windows (eg.: microsoft visual studio 2003) --> + <property name="VSINSTALLDIR" + location="${env.ProgramFiles}\Microsoft Visual Studio .NET 2003\Common7\IDE" /> + <property name="VCINSTALLDIR" + location="${env.ProgramFiles}\Microsoft Visual Studio .NET 2003" /> + <property name="MSVCDir" + location="${VCINSTALLDIR}\VC7" /> + <property name="DevEnvDir" + location="${VSINSTALLDIR}" /> + <property name="VellemanDir" + location="C:\Program Files\Velleman\K8055" /> + + <target name="init"> + <echo message="running ant '${ant.version}'" level="info" /> + <echo message="on java '${ant.java.version}'" level="info" /> + <echo message="java.home='${java.home}'" level="info" /> + <echo message="jdk.home ='${jdk.home}'" level="info" /> + <mkdir dir="build/java" /> + <mkdir dir="build/c" /> + <mkdir dir="dist" /> + <mkdir dir="dist/win32" /> + <mkdir dir="dist/linux" /> + </target> + + <target name="compile-java" depends="init"> + <javac srcdir="src/java" destdir="build/java"> + <include name="**/*.java"/> + <exclude name="**/*Test.java"/> + </javac> + <javah classpath="build/java" + class="net.sf.libk8055.jk8055.JK8055" + outputfile="build/c/jk8055.h" /> + </target> + + <target name="compile-c" depends="compile-java"> + <javah classpath="build/java" + class="net.sf.libk8055.jk8055.JK8055" + outputfile="build/c/jk8055.h" /> + <exec executable="gcc" dir="build/c" os="Linux"> + <arg line='-o lib${file.base}.so + -shared + -Wl,-soname,lib${file.base}.so + -I${jdk.home}/include + -I${jdk.home}/include/linux + -I. + -lk8055 + "${file.c}"' /> + </exec> + <exec executable="${MSVCDir}\BIN\cl.exe" dir="build/c" + os="Windows 2000, Windows XP" failonerror="true"> + <!-- be carefull with case here ! --> + <env key="Path" path="${DevEnvDir};${MSVCDir}\BIN;${env.Path}" /> + <env key="INCLUDE" path="${MSVCDir}\INCLUDE;${env.INCLUDE}" /> + <env key="LIB" path="${MSVCDir}\LIB;${env.LIB}" /> + <arg line='-I "${jdk.home}\include" + -I "${jdk.home}\include\win32" + -I "${VellemanDir}" + -I. + -DUSE_VELLEMAN_DLL + -LD + "${file.c}" + -Fe${file.base}.dll + -link "${VellemanDir}\K8055D_C.lib"' /> + </exec> + </target> + + <target name="dist" depends="compile-c" + description="create files for distribution"> + <copy todir="dist/linux" failonerror="false"> + <fileset dir="build/c"> + <include name="lib${file.base}.so"/> + </fileset> + </copy> + <copy todir="dist/win32" failonerror="false"> + <fileset dir="build/c"> + <include name="${file.base}.dll"/> + </fileset> + <fileset dir="${VellemanDir}"> + <include name="K8055D_C.DLL"/> + <include name="K8055D.DLL"/> + </fileset> + </copy> + <jar destfile="dist/${file.base}-${version}.jar" basedir="build/java"> + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="JK8055-Version" value="${version}"/> + </manifest> + </jar> + </target> + + <target name="javadoc" depends="compile-java" + description="create component Javadoc documentation"> + <mkdir dir="build/docs"/> + <mkdir dir="build/docs/api"/> + <javadoc destdir="build/docs/api" + overview="src/java/net/sf/libk8055/jk8055/overview.html" + packagenames="net.sf.libk8055.jk8055" + author="true" + version="true" + doctitle="<h1>JK8055</h1>" + windowtitle="JK8055 (Version ${version})" + bottom="Copyright &copy; 2008 by Martin Pischky" + use="true" + link="http://java.sun.com/j2se/1.4/docs/api/"> + <fileset dir="src/java"> + <include name="**/*.java"/> + <exclude name="**/*Test.java"/> + </fileset> + </javadoc> + <jar jarfile="dist/${file.base}-${version}-javadoc.jar" + basedir="build/docs/api" /> + </target> + + <target name="junit" depends="compile-c" + description="run junit tests" > + <!-- we assume that junit.jar is in ant's lib directory --> + <mkdir dir="build/reports" /> + <mkdir dir="build/junit" /> + <javac srcdir="src/java" destdir="build/junit"> + <include name="**/*Test.java"/> + </javac> + <junit printsummary="yes" + haltonfailure="yes" showoutput="yes"> + <classpath> + <pathelement location="build/java" /> + <pathelement location="build/junit" /> + <pathelement path="${java.class.path}" /> + </classpath> + <env key="Path" path="build/c;${VellemanDir};${env.Path}"/> + <env key="LD_LIBRARY_PATH" path="build/c:${env.LD_LIBRARY_PATH}"/> + <formatter type="plain"/> + <batchtest fork="yes" todir="build/reports"> + <fileset dir="src/java"> + <include name="**/*Test.java"/> + </fileset> + </batchtest> + </junit> + </target> + + <target name="all" depends="dist, javadoc" + description="--> java wrapper for libk8055"> + </target> + + <target name="clean"> + <delete dir="build"/> + </target> + + <target name="distclean" depends="clean"> + <delete dir="dist"/> + </target> + +</project> + + diff --git a/java/src/c/jk8055.c b/java/src/c/jk8055.c new file mode 100644 index 0000000..e33de70 --- /dev/null +++ b/java/src/c/jk8055.c @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2008 Martin Pischky (mailto:martin@pischky.de) + * + * This file (jk8055.c) is part of libk8055/jk8055. + * jk8055 - a java wrapper for libk8055 + * + * libk8055/jk8055 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * $Id: jk8055.c,v 1.2 2008/07/12 11:32:01 pischky Exp $ + * + */ + +#include <jni.h> +#ifdef USE_VELLEMAN_DLL + // assumes that Velleman DLL Version 2 has been installed + #define bool int + #include <K8055D_C.h> +#else + // assumes that the c library as been installed with header file + #include <k8055.h> +#endif +#include <stdio.h> +#include "jk8055.h" + +#define K8055_ERROR -1 + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: COpenDevice + * Signature: (I)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_COpenDevice +(JNIEnv* env, jobject obj, jint cardAddress) +{ + return OpenDevice(cardAddress); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CCloseDevice + * Signature: ()I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CCloseDevice +(JNIEnv* env, jobject obj) +{ + return CloseDevice(); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CReadAnalogChannel + * Signature: (I)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CReadAnalogChannel +(JNIEnv* env, jobject obj, jint channel) +{ + return ReadAnalogChannel( channel ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CReadAllAnalog + * Signature: (Lnet/sf/libk8055/jk8055/JK8055$AllAnalog;)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CReadAllAnalog +(JNIEnv* env, jobject obj, jobject data) +{ + long a1, a2; + jfieldID fid1, fid2; + int retval; + jclass cls; + + retval = ReadAllAnalog( &a1, &a2 ); + if( retval == K8055_ERROR ) return retval; + cls = (*env)->GetObjectClass( env, data ); + fid1 = (*env)->GetFieldID( env, cls, "data1", "I" ); + if( fid1 == NULL ) return K8055_ERROR; + fid2 = (*env)->GetFieldID( env, cls, "data2", "I" ); + if( fid2 == NULL ) return K8055_ERROR; + (*env)->SetIntField( env, data, fid1, (jint) a1 ); + (*env)->SetIntField( env, data, fid2, (jint) a2 ); + return 0; +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: COutputAnalogChannel + * Signature: (II)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_COutputAnalogChannel +(JNIEnv* env, jobject obj, jint channel, jint data) +{ + return OutputAnalogChannel( channel, data ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: COutputAllAnalog + * Signature: (II)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_COutputAllAnalog +(JNIEnv* env, jobject obj, jint data1, jint data2) +{ + return OutputAllAnalog( data1, data2 ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CClearAllAnalog + * Signature: ()I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CClearAllAnalog +(JNIEnv* env, jobject obj) +{ + return ClearAllAnalog(); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CClearAnalogChannel + * Signature: (I)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CClearAnalogChannel +(JNIEnv* env, jobject obj, jint channel) +{ + return ClearAnalogChannel( channel ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CSetAnalogChannel + * Signature: (I)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CSetAnalogChannel +(JNIEnv* env, jobject obj, jint channel) +{ + return SetAnalogChannel( channel ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CSetAllAnalog + * Signature: ()I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CSetAllAnalog +(JNIEnv* env, jobject obj) +{ + return SetAllAnalog(); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CWriteAllDigital + * Signature: (I)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CWriteAllDigital +(JNIEnv* env, jobject obj, jint data) +{ + return WriteAllDigital( data ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CClearDigitalChannel + * Signature: (I)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CClearDigitalChannel +(JNIEnv* env, jobject obj, jint channel) +{ + return ClearDigitalChannel( channel ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CClearAllDigital + * Signature: ()I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CClearAllDigital +(JNIEnv* env, jobject obj) +{ + return ClearAllDigital(); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CSetDigitalChannel + * Signature: (I)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CSetDigitalChannel +(JNIEnv* env, jobject obj, jint channel) +{ + return SetDigitalChannel( channel ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CSetAllDigital + * Signature: ()I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CSetAllDigital +(JNIEnv* env, jobject obj) +{ + return SetAllDigital(); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CReadDigitalChannel + * Signature: (I)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CReadDigitalChannel +(JNIEnv* env, jobject obj, jint channel) +{ + return ReadDigitalChannel( channel ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CReadAllDigital + * Signature: ()I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CReadAllDigital +(JNIEnv* env, jobject obj) +{ + return ReadAllDigital(); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CResetCounter + * Signature: (I)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CResetCounter +(JNIEnv* env, jobject obj, jint counterno) +{ + return ResetCounter( counterno ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CReadCounter + * Signature: (I)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CReadCounter +(JNIEnv* env, jobject obj, jint counterno) +{ + return ReadCounter( counterno ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CSetCounterDebounceTime + * Signature: (II)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CSetCounterDebounceTime +(JNIEnv* env, jobject obj, jint counterno, jint debouncetime) +{ + return SetCounterDebounceTime( counterno, debouncetime ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CReadAllValues + * Signature: (Lnet/sf/libk8055/jk8055/JK8055$AllValues;)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CReadAllValues +(JNIEnv* env, jobject obj, jobject av) +{ + long input, analog1, analog2, counter1, counter2; + int retval; + jfieldID fid_input, fid_analog1, fid_analog2, fid_counter1, fid_counter2; + jclass cls; + + #ifdef USE_VELLEMAN_DLL + input = ReadAllDigital(); + if( input == K8055_ERROR ) return input; + retval = ReadAllAnalog( &analog1, &analog2 ); + if( retval == K8055_ERROR ) return retval; + counter1 = ReadCounter( 1 ); + if( counter1 == K8055_ERROR ) return counter1; + counter2 = ReadCounter( 2 ); + if( counter2 == K8055_ERROR ) return counter2; + #else + retval = ReadAllValues( &input, &analog1, &analog2, &counter1, &counter2 ); + if( retval == K8055_ERROR ) return retval; + #endif + cls = (*env)->GetObjectClass( env, av ); + fid_input = (*env)->GetFieldID( env, cls, "input", "I" ); + if( fid_input == NULL ) return K8055_ERROR; + fid_analog1 = (*env)->GetFieldID( env, cls, "analog1", "I" ); + if( fid_analog1 == NULL ) return K8055_ERROR; + fid_analog2 = (*env)->GetFieldID( env, cls, "analog2", "I" ); + if( fid_analog2 == NULL ) return K8055_ERROR; + fid_counter1 = (*env)->GetFieldID( env, cls, "counter1", "I" ); + if( fid_counter1 == NULL ) return K8055_ERROR; + fid_counter2 = (*env)->GetFieldID( env, cls, "counter2", "I" ); + if( fid_counter2 == NULL ) return K8055_ERROR; + (*env)->SetIntField( env, av, fid_input, (jint) input ); + (*env)->SetIntField( env, av, fid_analog1, (jint) analog1 ); + (*env)->SetIntField( env, av, fid_analog2, (jint) analog2 ); + (*env)->SetIntField( env, av, fid_counter1, (jint) counter1 ); + (*env)->SetIntField( env, av, fid_counter2, (jint) counter2 ); + return 0; +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CSetAllValues + * Signature: (III)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CSetAllValues +(JNIEnv* env, jobject obj, jint digitaldata, jint analogdata1, jint analogdata2) +{ + int retval; + #ifdef USE_VELLEMAN_DLL + retval = WriteAllDigital( digitaldata ); + if( retval == K8055_ERROR ) return retval; + retval = OutputAllAnalog( analogdata1, analogdata2 ); + if( retval == K8055_ERROR ) return retval; + #else + retval = SetAllValues( digitaldata, analogdata1, analogdata2 ); + #endif + return retval; +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CSetCurrentDevice + * Signature: (I)I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CSetCurrentDevice +(JNIEnv* env, jobject obj, jint deviceno) +{ + return SetCurrentDevice( deviceno ); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CSearchDevices + * Signature: ()I + */ +JNIEXPORT jint +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CSearchDevices +(JNIEnv* env, jobject obj) +{ + return SearchDevices(); +} + +/* + * Class: net_sf_libk8055_jk8055_JK8055 + * Method: CVersion + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring +JNICALL Java_net_sf_libk8055_jk8055_JK8055_CVersion +(JNIEnv* env, jobject obj) +{ + #ifdef USE_VELLEMAN_DLL + return (*env)->NewStringUTF( env, "unknown" ); + #else + return (*env)->NewStringUTF( env, Version() ); + #endif +} diff --git a/java/src/java/net/sf/libk8055/jk8055/JK8055.java b/java/src/java/net/sf/libk8055/jk8055/JK8055.java new file mode 100644 index 0000000..26cdbc1 --- /dev/null +++ b/java/src/java/net/sf/libk8055/jk8055/JK8055.java @@ -0,0 +1,812 @@ +/* + * Copyright (C) 2008 Martin Pischky (mailto:martin@pischky.de) + * + * This file (JK8055.java) is part of libk8055/jk8055. + * jk8055 - a java wrapper for libk8055 + * + * libk8055/jk8055 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * $Id: JK8055.java,v 1.4 2008/07/28 09:58:30 pischky Exp $ + * + */ + +package net.sf.libk8055.jk8055; + +/** + * JK8055 - A java wrapper for libk8055. + * + * @see <a href="http://libk8055.sourceforge.net/">http://libk8055.sourceforge.net/</a> + * @author <a href="mailto:martin@pischky.de">Martin Pischky</a> + * + */ +public class JK8055 { + + public static final String CVS_ID = "$Id: JK8055.java,v 1.4 2008/07/28 09:58:30 pischky Exp $"; + + /** + * This class is singleton. + */ + private JK8055() { + } + + private static JK8055 instance = null; + + /** + * Create an instance if needed and return it. + * @return the instance + */ + public static JK8055 getInstance() { + if( instance != null ) { + return instance; + } + synchronized (JK8055.class) { + if( instance == null ) { + instance = new JK8055(); + } + } + return instance; + } + + public static final int K8055_ERROR = -1; + + static { + System.loadLibrary("jk8055"); + } + + /* (non-Javadoc) + * @see java.lang.Object#finalize() + */ + protected void finalize() throws Throwable { + try { + CloseAllOpenDevices(); + } finally { + super.finalize(); + } + } + + /** + * Open device. + * Scan through usb busses looking + * for the right device, claim it and then open the device. + * @param cardAddress + * @return BoardAddress or K8055_ERROR + */ + private native int COpenDevice( int cardAddress ); + + /** + * Opens the communication link to the K8055 device. + * Opens the communication link to the K8055 card. Loads the drivers + * needed to communicate via the USB port. This procedure must be performed + * before any attempts to communicate with the K8055 card. + * <br> + * This function can also be used to selects the active K8055 card to read + * and write the data. All the communication routines after this function + * call are addressed to this card until the other card is selected by this + * function call. + * + * @param cardAddress Value between 0 and 3 which corresponds to the + * jumper (SK5, SK6) setting on the K8055 board. + * @return If succeeded the return value will be the card address read + * from the K8055 hardware. + * @throws JK8055Exception indicates that K8055 card was not found. + */ + public synchronized int OpenDevice( int cardAddress ) + throws JK8055Exception + { + if( cardAddress<0 || 3<cardAddress ) { + throw new IllegalArgumentException( "cardAddress: "+cardAddress ); + } + int retval = COpenDevice( cardAddress ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "OpenDevice("+cardAddress+") failed" ); + } + return retval; + } + + /** + * Close the Current device. + * @return retunvalue from usb_close: 0 on success or < 0 on error. + */ + private native int CCloseDevice(); + + /** + * Closes the link to the K8055 device. + * Unloads the communication routines for K8055 card and unloads the driver + * needed to communicate via the USB port. This is the last action of the + * application program before termination. + * + * @throws JK8055Exception indicates an error. + */ + public synchronized void CloseDevice() + throws JK8055Exception + { + int retval = CCloseDevice(); + if( retval<0 ) { + throw new JK8055Exception( "CloseDevice failed with rc="+retval ); + } + } + + /** + * Close all open devices. + * Check what open devices still exist an closes them. + * + * @throws JK8055Exception + */ + public synchronized void CloseAllOpenDevices() + throws JK8055Exception + { + for( int i = 0; i < 4; i++ ) { + if( CSetCurrentDevice( i ) != K8055_ERROR ) { + CloseDevice(); + } + } + } + + /** + * @param channel 1..2 + * @return 0..255 or K8055_ERROR + */ + private native int CReadAnalogChannel( int channel ); + + /** + * Reads the status of one analogue input-channel. + * The input voltage of the selected 8-bit Analogue to Digital converter + * channel is converted to a value which lies between 0 and 255. + * + * @param channel Value between 1 and 2 which corresponds to the AD channel + * whose status is to be read. + * @return The corresponding Analogue to Digital Converter data is read. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid channel number. + */ + public synchronized int ReadAnalogChannel( int channel ) + throws JK8055Exception + { + if( channel<1 || 2<channel ) { + throw new IllegalArgumentException( "channel: "+channel ); + } + int retval = CReadAnalogChannel( channel ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "ReadAnalogChannel failed" ); + } + return retval; + } + + public class AllAnalog { + public int data1; + public int data2; + } + + /** + * @param data + * @return 0 or K8055_ERROR + */ + private native int CReadAllAnalog(AllAnalog data); + + /** + * Reads the status of both analogue input-channels. + * The status of both Analogue to Digital Converters are read to a new + * object of class AllAnalogarray + * + * @return the values read + * @throws JK8055Exception indicates an error. + */ + public synchronized AllAnalog ReadAllAnalog() + throws JK8055Exception + { + AllAnalog aa = new AllAnalog(); + int retval = CReadAllAnalog( aa ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "ReadAllAnalog failed" ); + } + return aa; + } + + /** + * @param channel 1..2 + * @param data 0..255 + * @return K8055_ERROR or 0 + */ + private native int COutputAnalogChannel( int channel, int data ); + + /** + * Sets the analogue output channel according to the data. + * The indicated 8-bit Digital to Analogue Converter channel is altered + * according to the new data. This means that the data corresponds to a + * specific voltage. The value 0 corresponds to a minimum output voltage + * (0 Volt) and the value 255 corresponds to a maximum output voltage + * (+5V). A value of 'Data' lying in between these extremes can be + * translated by the following formula : Data / 255 x 5V. + * + * @param channel Value between 1 and 2 which corresponds to the 8-bit DA + * channel number whose data is to be set. + * @param data Value between 0 and 255 which is to be sent to the 8-bit + * Digital to Analogue Converter. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid parameter. + */ + public synchronized void OutputAnalogChannel( int channel, int data ) + throws JK8055Exception + { + if( channel<1 || 2<channel ) { + throw new IllegalArgumentException( "channel: "+channel ); + } + if( data<0 || 255<data ) { + throw new IllegalArgumentException( "data: "+data ); + } + int retval = COutputAnalogChannel( channel, data ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "OutputAnalogChannel failed" ); + } + } + + /** + * @param data1 0..255 + * @param data2 0..255 + * @return K8055_ERROR or 0 + */ + private native int COutputAllAnalog( int data1, int data2 ); + + /** + * Sets both analogue output channels according to the data. + * Both 8-bit Digital to Analogue Converter channels are altered according + * to the new data. This means that the data corresponds to a specific + * voltage. The value 0 corresponds to a minimum output voltage (0 Volt) + * and the value 255 corresponds to a maximum output voltage (+5V). A + * value of 'Data1' or 'Data2' lying in between these extremes can be + * translated by the following formula : Data / 255 x 5V. + * + * @param data1 Value between 0 and 255 which is to be sent to the 8-bit + * Digital to Analogue Converter. + * @param data2 Value between 0 and 255 which is to be sent to the 8-bit + * Digital to Analogue Converter. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid parameter. + */ + public synchronized void OutputAllAnalog( int data1, int data2 ) + throws JK8055Exception + { + if( data1<0 || 255<data1 ) { + throw new IllegalArgumentException( "data1: "+data1 ); + } + if( data2<0 || 255<data2 ) { + throw new IllegalArgumentException( "data2: "+data2 ); + } + int retval = COutputAllAnalog( data1, data2 ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "OutputAllAnalog failed" ); + } + } + + /** + * @return K8055_ERROR or 0 + */ + private native int CClearAllAnalog(); + + /** + * Sets all analogue output channels to minimum. + * Both DA-channels are set to minimum output voltage (0 Volt) . + * + * @throws JK8055Exception indicates an error. + */ + public synchronized void ClearAllAnalog() + throws JK8055Exception + { + int retval = CClearAllAnalog(); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "ClearAllAnalog failed" ); + } + } + + /** + * @param channel 1..2 + * @return K8055_ERROR or 0 + */ + private native int CClearAnalogChannel( int channel ); + + /** + * Sets the analogue output channel to minimum. + * The selected DA-channel is set to minimum output voltage (0 Volt). + * + * @param channel Value between 1 and 2 which corresponds to the 8-bit DA + * channel number in which the data is to be erased. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid channel number. + */ + public synchronized void ClearAnalogChannel( int channel ) + throws JK8055Exception + { + if( channel<1 || 2<channel ) { + throw new IllegalArgumentException( "channel: "+channel ); + } + int retval = CClearAnalogChannel( channel ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "ClearAllAnalog failed" ); + } + } + + /** + * @param channel 1..2 + * @return K8055_ERROR or 0 + */ + private native int CSetAnalogChannel( int channel ); + + /** + * Sets the analogue output channel to maximum. + * The selected 8-bit Digital to Analogue Converter channel is set to + * maximum output voltage. + * + * @param channel Value between 1 and 2 which corresponds to the 8-bit DA + * channel number in which the data is to be set to maximum. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid channel number. + */ + public synchronized void SetAnalogChannel( int channel ) + throws JK8055Exception + { + if( channel<1 || 2<channel ) { + throw new IllegalArgumentException( "channel: "+channel ); + } + int retval = CSetAnalogChannel( channel ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "SetAnalogChannel failed" ); + } + } + + /** + * @return K8055_ERROR or 0 + */ + private native int CSetAllAnalog(); + + /** + * Sets all analogue output channels to maximum. + * All channels of the 8-bit Digital to Analogue Converters are set to + * maximum output voltage. + * + * @throws JK8055Exception indicates an error. + */ + public synchronized void SetAllAnalog() + throws JK8055Exception + { + int retval = CSetAllAnalog(); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "SetAllAnalog failed" ); + } + } + + /** + * @param data 0..255 + * @return K8055_ERROR or 0 + */ + private native int CWriteAllDigital( int data ); + + /** + * Sets the digital outputs according to the data. + * The channels of the digital output port are updated with the status of + * the corresponding bits in the data parameter. A high (1) level means + * that the microcontroller IC1 output is set, and a low (0) level means + * that the output is cleared. + * + * @param data Value between 0 and 255 that is sent to the output + * port (8 channels). + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid parameter. + */ + public synchronized void WriteAllDigital( int data ) + throws JK8055Exception + { + if( data<0 || 255<data ) { + throw new IllegalArgumentException( "data: "+data ); + } + int retval = CWriteAllDigital( data ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "WriteAllDigital failed" ); + } + } + + /** + * @param channel 1..8 + * @return K8055_ERROR or 0 + */ + private native int CClearDigitalChannel( int channel ); + + /** + * Clears the output channel. + * The selected channel is cleared. + * + * @param channel Value between 1 and 8 which corresponds to the output + * channel that is to be cleared. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid channel number. + */ + public synchronized void ClearDigitalChannel( int channel ) + throws JK8055Exception + { + if( channel<1 || 8<channel ) { + throw new IllegalArgumentException( "channel: "+channel ); + } + int retval = CClearDigitalChannel( channel ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "ClearDigitalChannel failed" ); + } + } + + /** + * @return K8055_ERROR or 0 + */ + private native int CClearAllDigital(); + + /** + * Clears all output channels. + * All digital outputs are cleared. + * + * @throws JK8055Exception indicates an error. + */ + public synchronized void ClearAllDigital() + throws JK8055Exception + { + int retval = CClearAllDigital(); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "ClearAllDigital failed" ); + } + } + + /** + * @param channel 1..8 + * @return K8055_ERROR or 0 + */ + private native int CSetDigitalChannel( int channel ); + + /** + * Sets the output channel. + * The selected digital output channel is set. + * + * @param channel Value between 1 and 8 which corresponds to the output + * channel that is to be set. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid channel number. + */ + public synchronized void SetDigitalChannel( int channel ) + throws JK8055Exception + { + if( channel<1 || 8<channel ) { + throw new IllegalArgumentException( "channel: "+channel ); + } + int retval = CSetDigitalChannel( channel ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "SetDigitalChannel failed" ); + } + } + + /** + * @return K8055_ERROR or 0 + */ + private native int CSetAllDigital(); + + /** + * Sets all output channels. + * All the digital output channels are set. + * + * @throws JK8055Exception indicates an error. + */ + public synchronized void SetAllDigital() + throws JK8055Exception + { + int retval = CSetAllDigital(); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "SetAllDigital failed" ); + } + } + + /** + * @param channel 1..5 + * @return K8055_ERROR or 0,1 + */ + private native int CReadDigitalChannel( int channel ); + + /** + * Reads the status of the input channel. + * The status of the selected Input channel is read. + * + * @param channel Value between 1 and 5 which corresponds to the input + * channel whose status is to be read. + * @return TRUE means that the channel has been set and FALSE means that + * it has been cleared. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid channel number. + */ + public synchronized boolean ReadDigitalChannel( int channel ) + throws JK8055Exception + { + if( channel<1 || 5<channel ) { + throw new IllegalArgumentException( "channel: "+channel ); + } + int retval = CReadDigitalChannel( channel ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "ReadDigitalChannel failed" ); + } + return retval != 0; + } + + /** + * @return K8055_ERROR or 0..31 + */ + private native int CReadAllDigital(); + + /** + * Reads the status of all the input channels. + * The function returns the status of the digital inputs. + * + * @return The 5 LSB correspond to the status of the input channels. A high + * (1) means that the channel is HIGH, a low (0) means that the + * channel is LOW. + * @throws JK8055Exception indicates an error. + */ + public synchronized int ReadAllDigital() + throws JK8055Exception + { + int retval = CReadAllDigital(); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "ReadAllDigital failed" ); + } + return retval; + } + + /** + * @param counterno 1..2 + * @return K8055_ERROR or 0 + */ + private native int CResetCounter( int counterno ); + + /** + * Resets the 16 bit pulse counter number 1 or counter number 2. + * The selected pulse counter is reset. + * + * @param counterno Value 1 or 2, which corresponds to the counter to + * be reset. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid counter number. + */ + public synchronized void ResetCount( int counterno ) + throws JK8055Exception + { + if( counterno<1 || 2<counterno ) { + throw new IllegalArgumentException( "counterno: "+counterno ); + } + int retval = CResetCounter( counterno ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "ResetCount failed" ); + } + } + + /** + * @param counterno 1..2 + * @return K8055_ERROR or 0..65535 + */ + private native int CReadCounter( int counterno ); + + /** + * Reads the content of the pulse counter number 1 or counter number 2. + * The function returns the status of the selected 16 bit pulse counter. + * <br> + * The counter number 1 counts the pulses fed to the input I1 and the + * counter number 2 counts the pulses fed to the input I2. + * + * @param counterno Value 1 or 2, which corresponds to the counter to be + * read. + * @return The content of the 16 bit pulse counter. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid counter number. + */ + public synchronized int ReadCounter( int counterno ) + throws JK8055Exception + { + if( counterno<1 || 2<counterno ) { + throw new IllegalArgumentException( "counterno: "+counterno ); + } + int retval = CReadCounter( counterno ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "ReadCounter failed" ); + } + return retval; + } + + /** + * @param counterno 1..2 + * @param debouncetime 0..7450 + * @return K8055_ERROR or 0 + */ + private native int CSetCounterDebounceTime( int counterno, int debouncetime ); + + /** + * Sets the debounce time to the pulse counter. + * The counter inputs are debounced in the software to prevent false + * triggering when mechanical switches or relay inputs are used. The + * debounce time is equal for both falling and rising edges. The + * default debounce time is 2ms. This means the counter input must be + * stable for at least 2ms before it is recognised, giving the maximum + * count rate of about 200 counts per second. + * <br> + * If the debounce time is set to 0, then the maximum counting rate is + * about 2000 counts per second. + * + * @param counterno Value 1 or 2, which corresponds to the counter + * to be set. + * @param debouncetime (0..7450?) Debounce time for the pulse counter. + * <br> + * The DebounceTime value corresponds to the debounce + * time in milliseconds (ms) to be set for the + * pulse counter. Debounce time value may vary between + * 0 and 5000?. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid parameter. + */ + public synchronized void SetCounterDebounceTime( int counterno, + int debouncetime ) + throws JK8055Exception + { + if( counterno<1 || 2<counterno ) { + throw new IllegalArgumentException( "counterno: "+counterno ); + } + if( debouncetime<0 || 7450<debouncetime ) { + throw new IllegalArgumentException( "debouncetime: "+debouncetime ); + } + int retval = CSetCounterDebounceTime( counterno, debouncetime ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "SetCounterDebounceTime failed" ); + } + } + + public class AllValues { + public int input; + public int analog1; + public int analog2; + public int counter1; + public int counter2; + } + + /** + * @param av + * @return K8055_ERROR or 0 + */ + private native int CReadAllValues( AllValues av ); + + /** + * Read all values at once. + * + * @return an new object of type AllValues + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid parameter. + */ + public synchronized AllValues ReadAllValues() + throws JK8055Exception + { + AllValues av = new AllValues(); + int retval = CReadAllValues( av ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "ReadAllValues failed" ); + } + return av; + } + + /** + * @param digitaldata 0..255 + * @param analogdata1 0..255 + * @param analogdata2 0..255 + * @return K8055_ERROR or 0 + */ + private native int CSetAllValues( int digitaldata, + int analogdata1, int analogdata2 ); + + /** + * Set all values at once. + * + * @param digitaldata 0..255 + * @param analogdata1 0..255 + * @param analogdata2 0..255 + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid parameter. + */ + public synchronized void SetAllValues( int digitaldata, + int analogdata1, int analogdata2 ) + throws JK8055Exception + { + if( digitaldata<1 || 255<digitaldata ) { + throw new IllegalArgumentException( "digitaldata: "+digitaldata ); + } + if( analogdata1<1 || 255<analogdata1 ) { + throw new IllegalArgumentException( "analogdata1: "+analogdata1 ); + } + if( analogdata2<1 || 255<analogdata2 ) { + throw new IllegalArgumentException( "analogdata2: "+analogdata2 ); + } + int retval = CSetAllValues( digitaldata, analogdata1, analogdata2); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "SetAllValues failed" ); + } + } + + /** + * @param deviceno 0..3 + * @return K8055_ERROR or 0..3 + */ + private native int CSetCurrentDevice( int deviceno ); + + /** + * The function set the current controlled device. + * If no device with the address parameter was found. + * an JK8055Exception is thrown. + * + * @param deviceno Value 0 to 3, which corresponds to the device address. + * @throws JK8055Exception indicates an error. + * @throws IllegalArgumentException indicates an invalid parameter. + */ + public synchronized void SetCurrentDevice( int deviceno ) + throws JK8055Exception + { + if( deviceno<0 || 3<deviceno ) { + throw new IllegalArgumentException( "deviceno: "+deviceno ); + } + int retval = CSetCurrentDevice( deviceno ); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "SetCurrentDevice failed" ); + } + } + + /** + * @return K8055_ERROR or 0..15 + */ + private native int CSearchDevices(); + + /** + * The function returns all connected devices on the computer. + * The returned value is a bit field. + * <br><b>Note</b> + * <br> Once a specific device address is connected with a program + * another program can't get access to it. + * + * @return + * <pre> + * Bin 0000, Dec 0 : No devices was found + * Bin 0001, Dec 1 : Card address 0 was found. + * Bin 0010, Dec 2 : Card address 1 was found. + * Bin 0100, Dec 4 : Card address 2 was found. + * Bin 1000, Dec 8 : Card address 3 was found. + * Example : return value 9 = devices with address 0 and 3 are connected. + * </pre> + * @throws JK8055Exception + */ + public synchronized int SearchDevices() + throws JK8055Exception + { + int retval = CSearchDevices(); + if( retval == K8055_ERROR ) { + throw new JK8055Exception( "SearchDevices failed" ); + } + return retval; + } + + private native String CVersion(); + + /** + * Return the version number of the libk8055 library used. + * + * @return a string like "0.3" + */ + public synchronized String Version() { + return CVersion(); + } + +} diff --git a/java/src/java/net/sf/libk8055/jk8055/JK8055Exception.java b/java/src/java/net/sf/libk8055/jk8055/JK8055Exception.java new file mode 100644 index 0000000..d0e7104 --- /dev/null +++ b/java/src/java/net/sf/libk8055/jk8055/JK8055Exception.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2008 Martin Pischky (mailto:martin@pischky.de) + * + * This file (JK8055Exception.java) is part of libk8055/jk8055. + * jk8055 - a java wrapper for libk8055 + * + * libk8055/jk8055 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * $Id: JK8055Exception.java,v 1.3 2008/07/14 07:47:55 pischky Exp $ + * + */ + +package net.sf.libk8055.jk8055; + +/** + * Exceptions thrown by class JK8055. + * + * @author Martin Pischky + */ +public class JK8055Exception extends Exception { + + public static final String CVS_ID = "$Id: JK8055Exception.java,v 1.3 2008/07/14 07:47:55 pischky Exp $"; + + /** + * + */ + private static final long serialVersionUID = 3821577565947420161L; + + /** + * Constructor. + */ + public JK8055Exception() { + super(); + } + + /** + * Constructor. + * @param message + */ + public JK8055Exception(String message) { + super(message); + } + + /** + * Constructor. + * @param cause + */ + public JK8055Exception(Throwable cause) { + super(cause); + } + + /** + * Constructor. + * @param message + * @param cause + */ + public JK8055Exception(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/java/src/java/net/sf/libk8055/jk8055/JK8055Test.java b/java/src/java/net/sf/libk8055/jk8055/JK8055Test.java new file mode 100644 index 0000000..c2c559c --- /dev/null +++ b/java/src/java/net/sf/libk8055/jk8055/JK8055Test.java @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2008 Martin Pischky (mailto:martin@pischky.de) + * + * This file (JK8055Test.java) is part of libk8055/jk8055. + * jk8055 - a java wrapper for libk8055 + * + * libk8055/jk8055 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * $Id: JK8055Test.java,v 1.4 2008/07/14 07:47:55 pischky Exp $ + * + */ + +package net.sf.libk8055.jk8055; + +import junit.framework.TestCase; + +/** + * JUnit tests for class JK8055. + * + * If you want to run this from eclipse add + * -Djava.library.path=build/c + * to VM arguments in run configuration. + * + * @author Martin Pischky + */ +public class JK8055Test extends TestCase { + + public static final int DEVICE = 0; + + /* + * @see TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + } + + /* + * @see TestCase#tearDown() + */ + protected void tearDown() throws Exception { + super.tearDown(); + } + + static void sleep( int ms ) { + try { + Thread.sleep( ms ); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public void testGetInstance() { + JK8055.getInstance(); + } + + public void testOpenCloseDevice() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.CloseDevice(); + } + + public void testReadAnalogChannel() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + int a1 = jk8055.ReadAnalogChannel(1); + int a2 = jk8055.ReadAnalogChannel(2); + assertTrue("a1>=0", a1>=0 ); + assertTrue("a1<=255",a1<=255); + assertTrue("a2>=0", a2>=0 ); + assertTrue("a2<=255",a2<=255); + jk8055.CloseDevice(); + } + + public void testReadAllAnalog() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + JK8055.AllAnalog aa = jk8055.ReadAllAnalog(); + assertTrue( "aa.data1>=0", aa.data1>=0 ); + assertTrue( "aa.data1<=255",aa.data1<=255 ); + assertTrue( "aa.data2>=0", aa.data2>=0 ); + assertTrue( "aa.data2<=255",aa.data2<=255 ); + int a1 = jk8055.ReadAnalogChannel(1); + int a2 = jk8055.ReadAnalogChannel(2); + assertTrue( "a1 ~= aa.data1", Math.abs(a1-aa.data1)<2 ); + assertTrue( "a2 ~= aa.data2", Math.abs(a2-aa.data2)<2 ); + jk8055.CloseDevice(); + } + + public void testOutputAnalogChannel() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.OutputAnalogChannel( 1, 0 ); + jk8055.OutputAnalogChannel( 2, 255 ); + sleep( 500 ); + for (int i = 0; i <= 255; i++) { + jk8055.OutputAnalogChannel( 1, i ); + jk8055.OutputAnalogChannel( 2, 255-i ); + } + for (int i = 255; i >= 0; i--) { + jk8055.OutputAnalogChannel( 1, i ); + jk8055.OutputAnalogChannel( 2, 255-i ); + } + sleep( 500 ); + jk8055.OutputAnalogChannel( 1, 0 ); + jk8055.OutputAnalogChannel( 2, 0 ); + jk8055.CloseDevice(); + } + + public void testOutputAllAnalog() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.OutputAllAnalog( 0, 255 ); + sleep( 500 ); + for (int i = 0; i <= 255; i++) { + jk8055.OutputAllAnalog( i, 255-i ); + } + for (int i = 255; i >= 0; i--) { + jk8055.OutputAllAnalog( i, 255-i ); + } + sleep( 500 ); + jk8055.OutputAllAnalog( 0, 0 ); + jk8055.CloseDevice(); + } + + public void testClearAllAnalog() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.ClearAllAnalog(); + jk8055.CloseDevice(); + } + + public void testClearAnalogChannel() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.ClearAnalogChannel( 1 ); + jk8055.ClearAnalogChannel( 2 ); + jk8055.CloseDevice(); + } + + public void testSetAnalogChannel() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.SetAnalogChannel( 1 ); + jk8055.SetAnalogChannel( 2 ); + jk8055.CloseDevice(); + } + + public void testSetAllAnalog() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.SetAllAnalog(); + jk8055.CloseDevice(); + } + + public void testWriteAllDigital() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.WriteAllDigital( 0 ); + for (int i = 0; i <= 7; i++) { + jk8055.WriteAllDigital( 1<<i ); + sleep( 50 ); + } + for (int i = 7; i >= 0; i--) { + jk8055.WriteAllDigital( 1<<i ); + sleep( 50 ); + } + jk8055.WriteAllDigital( 0 ); + jk8055.CloseDevice(); + } + + public void testClearDigitalChannel() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + for (int i = 1; i <= 8; i++) { + jk8055.ClearDigitalChannel( i ); + } + jk8055.CloseDevice(); + } + + public void testClearAllDigital() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.ClearAllDigital(); + jk8055.CloseDevice(); + } + + public void testSetDigitalChannel() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + for (int i = 1; i <= 8; i++) { + jk8055.SetDigitalChannel( i ); + } + jk8055.CloseDevice(); + } + + public void testSetAllDigital() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.SetAllDigital(); + jk8055.CloseDevice(); + } + + public void testReadDigitalChannel() throws JK8055Exception { + System.out.println( "---- testReadDigitalChannel()" ); + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + for (int i = 1; i <= 5; i++) { + boolean b = jk8055.ReadDigitalChannel( i ); + System.out.println( "Inp"+i+"="+b ); + } + jk8055.CloseDevice(); + } + + public void testReadAllDigital() throws JK8055Exception { + System.out.println( "---- testReadAllDigital()" ); + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + int data = jk8055.ReadAllDigital(); + assertTrue("data>=0", data>=0 ); + assertTrue("data<=255",data<=255); + for (int i = 1; i <= 5; i++) { + boolean b = (data & (1<<(i-1))) != 0; + System.out.println( "Inp"+i+"="+b ); + } + jk8055.CloseDevice(); + } + + public void testResetCount() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.ResetCount( 1 ); + jk8055.ResetCount( 2 ); + jk8055.CloseDevice(); + } + + public void testReadCounter() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + int c1 = jk8055.ReadCounter( 1 ); + int c2 = jk8055.ReadCounter( 2 ); + assertTrue( "c1", 0<=c1 && c1<=65535 ); + assertTrue( "c2", 0<=c2 && c2<=65535 ); + jk8055.CloseDevice(); + } + + public void testSetCounterDebounceTime() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.SetCounterDebounceTime( 1, 1214 ); + jk8055.SetCounterDebounceTime( 2, 1214 ); + jk8055.CloseDevice(); + } + + public void testReadAllValues() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + JK8055.AllValues av = jk8055.ReadAllValues(); + assertTrue( "av.input>=0", av.input>=0 ); + assertTrue( "av.input<=32", av.input<=32 ); + assertTrue( "av.analog1>=0", av.analog1>=0 ); + assertTrue( "av.analog1<=255", av.analog2<=255 ); + assertTrue( "av.analog2>=0", av.analog2>=0 ); + assertTrue( "av.analog2<=255", av.analog2<=255 ); + assertTrue( "av.counter1>=0", av.counter1>=0 ); + assertTrue( "av.counter1<=65535", av.counter1<=65535 ); + assertTrue( "av.counter2>=0", av.counter2>=0 ); + assertTrue( "av.counter2<=65535", av.counter2<=65535 ); + int a1 = jk8055.ReadAnalogChannel(1); + int a2 = jk8055.ReadAnalogChannel(2); + assertTrue( "a1 ~= aa.data1", Math.abs(a1-av.analog1)<2 ); + assertTrue( "a2 ~= aa.data2", Math.abs(a2-av.analog2)<2 ); + jk8055.CloseDevice(); + } + + public void testSetAllValues() throws JK8055Exception { + JK8055 jk8055 = JK8055.getInstance(); + jk8055.OpenDevice( DEVICE ); + jk8055.SetAllValues( 123, 232, 87 ); + jk8055.CloseDevice(); + } + + public void testSetCurrentDevice() throws JK8055Exception { + System.out.println( "---- testSetCurrentDevice()" ); + JK8055 jk8055 = JK8055.getInstance(); + int d = jk8055.SearchDevices(); + if( d == 0 ) { + System.out.println( "No devices found." ); + } else { + for (int i = 0; i <= 3; i++) { + if( (d & (1<<i)) != 0 ) { + System.out.println( "Device with card address "+i+" was found." ); + } + } + } + jk8055.CloseDevice(); // required for windows version ?!? + for (int i = 0; i <= 3; i++) { + if( (d & (1<<i)) != 0 ) { + System.out.println( "OpenDevice("+i+")" ); + jk8055.OpenDevice( i ); + } + } + for (int i = 0; i <= 3; i++) { + if( (d & (1<<i)) != 0 ) { + System.out.println( "SetCurrentDevice("+i+")" ); + jk8055.SetCurrentDevice( i ); + System.out.println( "WriteAllDigital("+(1<<i)+")" ); + jk8055.WriteAllDigital( 1<<i ); + } + } + for (int i = 0; i <= 3; i++) { + if( (d & (1<<i)) == 0 ) { + boolean exThrown = false; + try { + jk8055.SetCurrentDevice( i ); + } catch( JK8055Exception ex ) { + exThrown = true; + } + assertTrue( "exThrown", exThrown ); + } + } + for (int i = 0; i <= 3; i++) { + if( (d & (1<<i)) != 0 ) { + System.out.println( "SetCurrentDevice("+i+")" ); + jk8055.SetCurrentDevice( i ); + System.out.println( "CloseDevice()" ); + jk8055.CloseDevice(); + } + } + } + + public void testCloseAllOpenDevices() throws JK8055Exception { + System.out.println( "---- testCloseAllOpenDevices()" ); + JK8055 jk8055 = JK8055.getInstance(); + int d = jk8055.SearchDevices(); + if( d == 0 ) { + System.out.println( "No devices found." ); + } else { + for (int i = 0; i <= 3; i++) { + if( (d & (1<<i)) != 0 ) { + System.out.println( "Device with card address "+i+" was found." ); + } + } + } + jk8055.CloseDevice(); // required for windows version ?!? + for (int i = 0; i <= 3; i++) { + if( (d & (1<<i)) != 0 ) { + System.out.println( "OpenDevice("+i+")" ); + jk8055.OpenDevice( i ); + } + } + for (int i = 0; i <= 3; i++) { + if( (d & (1<<i)) != 0 ) { + System.out.println( "SetCurrentDevice("+i+")" ); + jk8055.SetCurrentDevice( i ); + System.out.println( "WriteAllDigital("+(1<<i)+")" ); + jk8055.WriteAllDigital( 1<<i ); + } + } + jk8055.CloseAllOpenDevices(); + } + + public void testSearchDevices() throws JK8055Exception { + System.out.println( "---- testSearchDevices()" ); + JK8055 jk8055 = JK8055.getInstance(); + //jk8055.OpenDevice( DEVICE ); + // Windows Version (Velleman DDL v2) + // does not return devices already opened + int d = jk8055.SearchDevices(); + if( d == 0 ) { + System.out.println( "No devices found." ); + } else { + for (int i = 0; i <= 3; i++) { + if( (d & (1<<i)) != 0 ) { + System.out.println( "Device with card address "+i+" was found." ); + } + } + } + jk8055.CloseDevice(); + } + + public void testVersion() { + System.out.println( "---- testVersion()" ); + assertNotNull( JK8055.getInstance().Version() ); + assertTrue( JK8055.getInstance().Version().length() > 0 ); + System.out.println( "version=\""+JK8055.getInstance().Version()+"\"" ); + } + +} diff --git a/java/src/java/net/sf/libk8055/jk8055/overview.html b/java/src/java/net/sf/libk8055/jk8055/overview.html new file mode 100644 index 0000000..2fff579 --- /dev/null +++ b/java/src/java/net/sf/libk8055/jk8055/overview.html @@ -0,0 +1,7 @@ +<html> +<body> +<p> +This document is the API specification for JK8055 - A java wrapper for libk8055. +</p> +</body> +</html> diff --git a/java/src/java/net/sf/libk8055/jk8055/package.html b/java/src/java/net/sf/libk8055/jk8055/package.html new file mode 100644 index 0000000..4dba573 --- /dev/null +++ b/java/src/java/net/sf/libk8055/jk8055/package.html @@ -0,0 +1,8 @@ +<html> +<body> +<p>JK8055 - A java wrapper for libk8055.</p> +<p>The wrapper can be used on Linux with libk8055 (see +<a href="http://libk8055.sourceforge.net/">http://libk8055.sourceforge.net/</a>) +or the standard Vellemann DLLs on Windows. +</body> +</html> @@ -0,0 +1,55 @@ +/* $Id: k8055.h,v 1.4 2008/05/21 20:25:51 mr_brain Exp $ + + This file is part of the libk8055 Library. + + The libk8055 Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The libk8055 Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + http://opensource.org/licenses/ +*/ +#ifdef __cplusplus +extern "C" { +#endif + +/* prototypes */ +int OpenDevice(long board_address); +int CloseDevice(); +long ReadAnalogChannel(long Channelno); +int ReadAllAnalog(long* data1, long* data2); +int OutputAnalogChannel(long channel, long data); +int OutputAllAnalog(long data1,long data2); +int ClearAllAnalog(); +int ClearAnalogChannel(long channel); +int SetAnalogChannel(long channel); +int SetAllAnalog(); +int WriteAllDigital(long data); +int ClearDigitalChannel(long channel); +int ClearAllDigital(); +int SetDigitalChannel(long channel); +int SetAllDigital(); +int ReadDigitalChannel(long channel); +long ReadAllDigital(); +int ResetCounter(long counternr); +long ReadCounter(long counterno); +int SetCounterDebounceTime(long counterno, long debouncetime); +int ReadAllValues (long int *data1, long int *data2, long int *data3, long int *data4, long int *data5); +int SetAllValues(int digitaldata, int addata1, int addata2); +long SetCurrentDevice(long deviceno); +long SearchDevices(void); +char *Version(void); +#ifdef __cplusplus +} +#endif + diff --git a/libk8055.c b/libk8055.c new file mode 100644 index 0000000..9556294 --- /dev/null +++ b/libk8055.c @@ -0,0 +1,600 @@ +/* $Id: libk8055.c,v 1.7 2008/08/20 17:00:55 mr_brain Exp $ + + This file is part of the libk8055 Library. + + The libk8055 Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The libk8055 Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + http://opensource.org/licenses/ + + Copyleft (C) 2005 by Sven Lindberg + k8055@k8055.mine.nu + + Copyright (C) 2007 by Pjetur G. Hjaltason + pjetur@pjetur.net + Commenting, general rearrangement of code, bugfixes, + python interface with swig and simple k8055 python class + + + Input packet format + + +---+---+---+---+---+---+---+---+ + |DIn|Sta|A1 |A2 | C1 | C2 | + +---+---+---+---+---+---+---+---+ + DIn = Digital input in high nibble, except for input 3 in 0x01 + Sta = Status, Board number + 1 + A1 = Analog input 1, 0-255 + A2 = Analog input 2, 0-255 + C1 = Counter 1, 16 bits (lsb) + C2 = Counter 2, 16 bits (lsb) + + Output packet format + + +---+---+---+---+---+---+---+---+ + |CMD|DIG|An1|An2|Rs1|Rs2|Dbv|Dbv| + +---+---+---+---+---+---+---+---+ + CMD = Command + DIG = Digital output bitmask + An1 = Analog output 1 value, 0-255 + An2 = Analog output 2 value, 0-255 + Rs1 = Reset counter 1, command 3 + Rs2 = Reset counter 3, command 4 + Dbv = Debounce value for counter 1 and 2, command 1 and 2 + + Or split by commands + + Cmd 0, Reset ?? + Cmd 1, Set debounce Counter 1 + +---+---+---+---+---+---+---+---+ + |CMD| | | | | |Dbv| | + +---+---+---+---+---+---+---+---+ + Cmd 2, Set debounce Counter 2 + +---+---+---+---+---+---+---+---+ + |CMD| | | | | | |Dbv| + +---+---+---+---+---+---+---+---+ + Cmd 3, Reset counter 1 + +---+---+---+---+---+---+---+---+ + | 3 | | | | 00| | | | + +---+---+---+---+---+---+---+---+ + Cmd 4, Reset counter 2 + +---+---+---+---+---+---+---+---+ + | 4 | | | | | 00| | | + +---+---+---+---+---+---+---+---+ + cmd 5, Set analog/digital + +---+---+---+---+---+---+---+---+ + | 5 |DIG|An1|An2| | | | | + +---+---+---+---+---+---+---+---+ + +**/ + +#include <string.h> +#include <stdio.h> +#include <usb.h> +#include <assert.h> +#include <math.h> +#include "k8055.h" + +#define STR_BUFF 256 +#define PACKET_LEN 8 + +#define K8055_IPID 0x5500 +#define VELLEMAN_VENDOR_ID 0x10cf +#define K8055_MAX_DEV 4 + +#define USB_OUT_EP 0x01 /* USB output endpoint */ +#define USB_INP_EP 0x81 /* USB Input endpoint */ + +#define USB_TIMEOUT 20 +#define K8055_ERROR -1 + +#define DIGITAL_INP_OFFSET 0 +#define DIGITAL_OUT_OFFSET 1 +#define ANALOG_1_OFFSET 2 +#define ANALOG_2_OFFSET 3 +#define COUNTER_1_OFFSET 4 +#define COUNTER_2_OFFSET 6 + +#define CMD_RESET 0x00 +#define CMD_SET_DEBOUNCE_1 0x01 +#define CMD_SET_DEBOUNCE_2 0x01 +#define CMD_RESET_COUNTER_1 0x03 +#define CMD_RESET_COUNTER_2 0x04 +#define CMD_SET_ANALOG_DIGITAL 0x05 + +/* set debug to 0 to not print excess info */ +int DEBUG = 0; + +/* variables for usb */ +static struct usb_bus *bus, *busses; +static struct usb_device *dev; + +/* globals for datatransfer */ +struct k8055_dev { + unsigned char data_in[PACKET_LEN+1]; + unsigned char data_out[PACKET_LEN+1]; + struct usb_dev_handle *device_handle; + int DevNo; +}; + +static struct k8055_dev k8055d[K8055_MAX_DEV]; +static struct k8055_dev *CurrDev; + +/* Keep these globals for now */ +unsigned char *data_in, *data_out; + +/* char* device_id[]; */ + +/* Initialize the usb library - only once */ +static void init_usb(void) +{ + static int Done = 0; /* Only need to do this once */ + if (!Done) + { + usb_init(); + usb_find_busses(); + usb_find_devices(); + busses = usb_get_busses(); + Done = 1; + } +} +/* Actual read of data from the device endpoint, retry 3 times if not responding ok */ +static int ReadK8055Data(void) +{ + int read_status = 0, i = 0; + + if (CurrDev->DevNo == 0) return K8055_ERROR; + + for(i=0; i < 3; i++) + { + read_status = usb_interrupt_read(CurrDev->device_handle, USB_INP_EP, (char *)CurrDev->data_in, PACKET_LEN, USB_TIMEOUT); + if ((read_status == PACKET_LEN) && (CurrDev->data_in[1] == CurrDev->DevNo )) return 0; + if (DEBUG) + fprintf(stderr, "Read retry\n"); + } + return K8055_ERROR; +} + +/* Actual write of data to the device endpont, retry 3 times if not reponding correctly */ +static int WriteK8055Data(unsigned char cmd) +{ + int write_status = 0, i = 0; + + if (CurrDev->DevNo == 0) return K8055_ERROR; + + CurrDev->data_out[0] = cmd; + for(i=0; i < 3; i++) + { + write_status = usb_interrupt_write(CurrDev->device_handle, USB_OUT_EP, (char *)CurrDev->data_out, PACKET_LEN, USB_TIMEOUT); + if (write_status == PACKET_LEN) return 0; + if (DEBUG) + fprintf(stderr, "Write retry\n"); + } + return K8055_ERROR; +} + +/* If device is owned by some kernel driver, try to disconnect it and claim the device*/ +static int takeover_device(usb_dev_handle * udev, int interface) +{ + char driver_name[STR_BUFF]; + + memset(driver_name, 0, STR_BUFF); + int ret = K8055_ERROR; + + assert(udev != NULL); + ret = usb_get_driver_np(udev, interface, driver_name, sizeof(driver_name)); + if (ret == 0) + { + if (DEBUG) + fprintf(stderr, "Got driver name: %s\n", driver_name); + if (0 > usb_detach_kernel_driver_np(udev, interface)) + { + if (DEBUG) + fprintf(stderr, "Disconnect OS driver: %s\n", usb_strerror()); + } + else if (DEBUG) + fprintf(stderr, "Disconnected OS driver: %s\n", usb_strerror()); + } + else if (DEBUG) + fprintf(stderr, "Get driver name: - %s\n", usb_strerror()); + + /* claim interface */ + if (usb_claim_interface(udev, interface) < 0) + { + if (DEBUG) + fprintf(stderr, "Claim interface error: %s\n", usb_strerror()); + return K8055_ERROR; + } + else + usb_set_altinterface(udev, interface); + usb_set_configuration(udev, 1); + + if (DEBUG) + { + fprintf(stderr, "Found interface %d\n", interface); + fprintf(stderr, "Took over the device\n"); + } + + return 0; +} + +/* Open device - scan through usb busses looking for the right device, + claim it and then open the device +*/ +int OpenDevice(long BoardAddress) +{ + + int ipid; + + /* init USB and find all of the devices on all busses */ + init_usb(); + + /* ID of the welleman board is 5500h + address config */ + if (BoardAddress >= 0 && BoardAddress < K8055_MAX_DEV) + ipid = K8055_IPID + (int)BoardAddress; + else + return K8055_ERROR; /* throw error instead of being nice */ + + /* start looping through the devices to find the correct one */ + for (bus = busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + if ((dev->descriptor.idVendor == VELLEMAN_VENDOR_ID) && + (dev->descriptor.idProduct == ipid)) + { + CurrDev = &k8055d[BoardAddress]; + CurrDev->device_handle = usb_open(dev); + if (DEBUG) + fprintf(stderr, + "Velleman Device Found @ Address %s Vendor 0x0%x Product ID 0x0%x\n", + dev->filename, dev->descriptor.idVendor, + dev->descriptor.idProduct); + if (takeover_device(CurrDev->device_handle, 0) < 0) + { + if (DEBUG) + fprintf(stderr, + "Can not take over the device from the OS driver\n"); + usb_close(CurrDev->device_handle); /* close usb if we fail */ + return K8055_ERROR; /* throw K8055_ERROR to show that OpenDevice failed */ + } + else + { + CurrDev->DevNo = BoardAddress + 1; /* Mark as open and valid */ + SetCurrentDevice(BoardAddress); + memset(CurrDev->data_out,0,PACKET_LEN); /* Write cmd 0, read data */ + WriteK8055Data(CMD_RESET); + if (ReadK8055Data() == 0) + return BoardAddress; /* This function should return board address */ + else + return K8055_ERROR; + } + } + } + } + if (DEBUG) + fprintf(stderr, "Could not find Velleman k8055 with address %d\n", + (int)BoardAddress); + return K8055_ERROR; +} + +/* Close the Current device */ +int CloseDevice() +{ + int rc; + + if (CurrDev->DevNo == 0) + { + if (DEBUG) + fprintf(stderr, "Current device is not open\n" ); + return 0; + } + rc = usb_close(CurrDev->device_handle); + if (rc >= 0) + { + CurrDev->DevNo = 0; /* Not active nay more */ + CurrDev->device_handle = NULL; + } + return rc; +} + +/* New function in version 2 of Velleman DLL, should return deviceno if OK */ +long SetCurrentDevice(long deviceno) +{ + if (deviceno >= 0 && deviceno < K8055_MAX_DEV) + { + if (k8055d[deviceno].DevNo != 0) + { + CurrDev = &k8055d[deviceno]; + data_in = CurrDev->data_in; + data_out = CurrDev->data_out; + return deviceno; + } + } + return K8055_ERROR; + +} + +/* New function in version 2 of Velleman DLL, should return devices-found bitmask or 0*/ +long SearchDevices(void) +{ + int retval = 0; + init_usb(); + /* start looping through the devices to find the correct one */ + for (bus = busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + if (dev->descriptor.idVendor == VELLEMAN_VENDOR_ID) { + if(dev->descriptor.idProduct == K8055_IPID + 0) retval |= 0x01; + if(dev->descriptor.idProduct == K8055_IPID + 1) retval |= 0x02; + if(dev->descriptor.idProduct == K8055_IPID + 2) retval |= 0x04; + if(dev->descriptor.idProduct == K8055_IPID + 3) retval |= 0x08; + /* else some other kind of Velleman board */ + } + } + } + return retval; +} + +long ReadAnalogChannel(long Channel) +{ + if (Channel == 1 || Channel == 2) + { + if ( ReadK8055Data() == 0) + { + if (Channel == 2) + return CurrDev->data_in[ANALOG_2_OFFSET]; + else + return CurrDev->data_in[ANALOG_1_OFFSET]; + } + else + return K8055_ERROR; + } + else + return K8055_ERROR; +} + +int ReadAllAnalog(long *data1, long *data2) +{ + if (ReadK8055Data() == 0) + { + *data1 = CurrDev->data_in[ANALOG_1_OFFSET]; + *data2 = CurrDev->data_in[ANALOG_2_OFFSET]; + return 0; + } + else + return K8055_ERROR; +} + +int OutputAnalogChannel(long Channel, long data) +{ + if (Channel == 1 || Channel == 2) + { + if (Channel == 2) + CurrDev->data_out[ANALOG_2_OFFSET] = (unsigned char)data; + else + CurrDev->data_out[ANALOG_1_OFFSET] = (unsigned char)data; + + return WriteK8055Data(CMD_SET_ANALOG_DIGITAL); + } + else + return K8055_ERROR; +} + +int OutputAllAnalog(long data1, long data2) +{ + CurrDev->data_out[2] = (unsigned char)data1; + CurrDev->data_out[3] = (unsigned char)data2; + + return WriteK8055Data(CMD_SET_ANALOG_DIGITAL); +} + +int ClearAllAnalog() +{ + return OutputAllAnalog(0, 0); +} + +int ClearAnalogChannel(long Channel) +{ + if (Channel == 1 || Channel == 2) + { + if (Channel == 2) + return OutputAnalogChannel(2, 0); + else + return OutputAnalogChannel(1, 0); + } + else + return K8055_ERROR; +} + +int SetAnalogChannel(long Channel) +{ + if (Channel == 1 || Channel == 2) + { + if (Channel == 2) + return OutputAnalogChannel(2, 0xff); + else + return OutputAnalogChannel(1, 0xff); + } + else + return K8055_ERROR; + +} + +int SetAllAnalog() +{ + return OutputAllAnalog(0xff, 0xff); +} + +int WriteAllDigital(long data) +{ + CurrDev->data_out[1] = (unsigned char)data; + return WriteK8055Data(CMD_SET_ANALOG_DIGITAL); +} + +int ClearDigitalChannel(long Channel) +{ + unsigned char data; + + if (Channel > 0 && Channel < 9) + { + data = CurrDev->data_out[1] & ~(1 << (Channel-1)); + return WriteAllDigital(data); + } + else + return K8055_ERROR; +} + +int ClearAllDigital() +{ + return WriteAllDigital(0x00); +} + +int SetDigitalChannel(long Channel) +{ + unsigned char data; + + if (Channel > 0 && Channel < 9) + { + data = CurrDev->data_out[1] | (1 << (Channel-1)); + return WriteAllDigital(data); + } + else + return K8055_ERROR; +} + +int SetAllDigital() +{ + return WriteAllDigital(0xff); +} + +int ReadDigitalChannel(long Channel) +{ + int rval; + if (Channel > 0 && Channel < 9) + { + if ((rval = ReadAllDigital()) == K8055_ERROR) return K8055_ERROR; + return ((rval & (1 << (Channel-1))) > 0); + } + else + return K8055_ERROR; +} + +long ReadAllDigital() +{ + int return_data = 0; + + if (ReadK8055Data() == 0) + { + return_data = ( + ((CurrDev->data_in[0] >> 4) & 0x03) | /* Input 1 and 2 */ + ((CurrDev->data_in[0] << 2) & 0x04) | /* Input 3 */ + ((CurrDev->data_in[0] >> 3) & 0x18) ); /* Input 4 and 5 */ + return return_data; + } + else + return K8055_ERROR; +} + +int ReadAllValues(long int *data1, long int * data2, long int * data3, long int * data4, long int * data5) +{ + if (ReadK8055Data() == 0) + { + *data1 = ( + ((CurrDev->data_in[0] >> 4) & 0x03) | /* Input 1 and 2 */ + ((CurrDev->data_in[0] << 2) & 0x04) | /* Input 3 */ + ((CurrDev->data_in[0] >> 3) & 0x18) ); /* Input 4 and 5 */ + *data2 = CurrDev->data_in[ANALOG_1_OFFSET]; + *data3 = CurrDev->data_in[ANALOG_2_OFFSET]; + *data4 = *((short int *)(&CurrDev->data_in[COUNTER_1_OFFSET])); + *data5 = *((short int *)(&CurrDev->data_in[COUNTER_2_OFFSET])); + return 0; + } + else + return K8055_ERROR; +} + +int SetAllValues(int DigitalData, int AdData1, int AdData2) +{ + CurrDev->data_out[1] = (unsigned char)DigitalData; + CurrDev->data_out[2] = (unsigned char)AdData1; + CurrDev->data_out[3] = (unsigned char)AdData2; + + return WriteK8055Data(CMD_SET_ANALOG_DIGITAL); +} + +int ResetCounter(long CounterNo) +{ + if (CounterNo == 1 || CounterNo == 2) + { + CurrDev->data_out[0] = 0x02 + (unsigned char)CounterNo; /* counter selection */ + CurrDev->data_out[3 + CounterNo] = 0x00; + return WriteK8055Data(CurrDev->data_out[0]); + } + else + return K8055_ERROR; +} + +long ReadCounter(long CounterNo) +{ + if (CounterNo == 1 || CounterNo == 2) + { + if (ReadK8055Data() == 0) + { + if (CounterNo == 2) + return *((short int *)(&CurrDev->data_in[COUNTER_2_OFFSET])); + else + return *((short int *)(&CurrDev->data_in[COUNTER_1_OFFSET])); + } + else + return K8055_ERROR; + } + else + return K8055_ERROR; +} + +int SetCounterDebounceTime(long CounterNo, long DebounceTime) +{ + float value; + + if (CounterNo == 1 || CounterNo == 2) + { + CurrDev->data_out[0] = (unsigned char)CounterNo; + /* the velleman k8055 use a exponetial formula to split up the + DebounceTime 0-7450 over value 1-255. I've tested every value and + found that the formula dbt=0,338*value^1,8017 is closest to + vellemans dll. By testing and measuring times on the other hand I + found the formula dbt=0,115*x^2 quite near the actual values, a + little below at really low values and a little above at really + high values. But the time set with this formula is within +-4% */ + if (DebounceTime > 7450) + DebounceTime = 7450; + value = sqrtf(DebounceTime / 0.115); + if (value > ((int)value + 0.49999999)) /* simple round() function) */ + value += 1; + CurrDev->data_out[5 + CounterNo] = (unsigned char)value; + if (DEBUG) + fprintf(stderr, "Debouncetime%d value for k8055:%d\n", + (int)CounterNo, CurrDev->data_out[5 + CounterNo]); + return WriteK8055Data(CurrDev->data_out[0]); + } + else + return K8055_ERROR; +} + +char * Version(void) +{ + return(VERSION); +} @@ -0,0 +1,295 @@ +/* $Id: main.c,v 1.3 2007/03/15 14:37:58 pjetur Exp $ + *************************************************************************** + * Copyright (C) 2004 by Nicolas Sutre * + * nicolas.sutre@free.fr * + * * + * Copyright (C) 2005 by Bob Dempsey * + * bdempsey_64@msn.com * + * * + * Copyright (C) 2005 by Julien Etelain and Edward Nys * + * Converted to C * + * Commented and improved by Julien Etelain <julien.etelain@utbm.fr> * + * Edward Nys <edward.ny@utbm.fr> * + * * + * Copyleft (L) 2005 by Sven Lindberg * + * k8055@k8055.mine.nu * + * Give it up already :) Simplified (read improved..) and included * + * with k8055 lib and with a functional man page * + * * + * 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. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <string.h> +#include <stdio.h> +#include <usb.h> +#include <assert.h> +#include <sys/time.h> +#include "k8055.h" + +#define STR_BUFF 256 +#define false 0 +#define true 1 + +extern int DEBUG; + +int ia1 = -1; +int ia2 = -1; +int id8 = -1; +int ipid = 0; + +int numread = 1; + +int debug = 0; + +int dbt1 = -1; // (-1 => not to set) +int dbt2 = -1; // (-1 => not to set) + +int resetcnt1 = false; +int resetcnt2 = false; + +int delay = 0; + +/* + Convert a string on n chars to an integer + Return 1 on sucess + 0 on failure (non number) +*/ +int Convert_StringToInt(char *text, int *i) +{ + return sscanf(text, "%d", i); +} + +/* + Write help to standard output +*/ +void display_help ( char *params[] ) { + + printf("K8055 version %s MrBrain Build\n",Version()); + printf("Copyright (C) 2004 by Nicolas Sutre\n"); + printf("Copyright (C) 2005 by Bob Dempsey\n"); + printf("Copyright (C) 2005 by Julien Etelain and Edward Nys\n"); + printf("Copyleft (L) 2005 by Sven Lindberg\n"); + printf("\n"); + printf("Syntax : %s [-p:(number)] [-d:(value)] [-a1:(value)] [-a2:(value)]\n",params[0]); + printf(" [-num:(number) [-delay:(number)] [-dbt1:(value)]\n"); + printf(" [-dbt2:(value)] [-reset1] [-reset2] [-debug]\n"); + printf(" -p:(number) Set board number\n"); + printf(" -d:(value) Set digital output value (8 bits in decimal)\n"); + printf(" -a1:(value) Set analog output 1 value (0-255)\n"); + printf(" -a2:(value) Set analog output 2 value (0-255)\n"); + printf(" -num:(number) Set number of measures\n"); + printf(" -delay:(number) Set delay between two measure (in msec)\n"); + printf(" -dbt1:(value) Set debounce time for counter 1 (in msec)\n"); + printf(" -dbt2:(value) Set debounce time for counter 2 (in msec)\n"); + printf(" -reset1 Reset counter 1\n"); + printf(" -reset2 Reset counter 2\n"); + printf(" -debug Activate debug mode\n"); + printf("Example : %s -p:1 -d:147 -a1:25 -a2:203\n",params[0]); + printf("\n"); + printf("Output : (timestamp);(digital);(analog 1);(analog 2);(counter 1);(counter 2)\n"); + printf("Note : timestamp is the number of msec when data is read since program start\n"); + printf("Example : 499;16;128;230;9;8\n"); + printf("499 : Measure done 499 msec after program start\n"); + +} + + +/* + Read arguments, and store values + Return true if arguments are valid + else return false +*/ +int read_param(int argc,char *params[]) +{ + int erreurParam = false; + int i; + + ipid = 0; + + for (i=1; i<argc;i++) + { + if ( !strncmp(params[i],"-p:",3) && + !Convert_StringToInt(params[i]+3,&ipid) ) erreurParam = true; + else + if ( !strncmp(params[i],"-a1:",4) && + !Convert_StringToInt(params[i]+4,&ia1) ) erreurParam = true; + else + if ( !strncmp(params[i],"-a2:",4) && + !Convert_StringToInt(params[i]+4,&ia2) ) erreurParam = true; + else + if ( !strncmp(params[i],"-d:",3) && + !Convert_StringToInt(params[i]+3,&id8) ) erreurParam = true; + else + if ( !strncmp(params[i],"-num:",5) && + !Convert_StringToInt(params[i]+5,&numread) ) erreurParam = true; + else + if ( !strncmp(params[i],"-delay:",7) && + !Convert_StringToInt(params[i]+7,&delay) ) erreurParam = true; + else + if ( !strncmp(params[i],"-dbt1:",6) && + !Convert_StringToInt(params[i]+6,&dbt1) ) erreurParam = true; + else + if ( !strncmp(params[i],"-dbt2:",6) && + !Convert_StringToInt(params[i]+6,&dbt2) ) erreurParam = true; + else + if ( !strcmp(params[i],"-debug") ){ + debug = true; + DEBUG = true; + } + else + if ( !strcmp(params[i],"-reset1") ) resetcnt1 = true; + else + if ( !strcmp(params[i],"-reset2") ) resetcnt2 = true; + else + if ( !strcmp(params[i],"--help") ) { + display_help(params); + return false; + } + + } + + + /* + Send parameters to standart error + */ + if ( debug ) + fprintf(stderr,"Parameters : Card=%d Analog1=%d Analog2=%d Digital=%d\n",ipid,ia1,ia2,id8); + + if (ipid<0 || ipid>3){ + printf("Invalid board address!\n"); + return -1; + } + + + if (erreurParam) + { + + printf("Invalid or incomplete options\n"); + + display_help(params); + return false; + } + + + return true; +} + +/* + Give current timestamp in miliseconds +*/ +inline unsigned long int time_msec ( void ) { + struct timeval t; struct timezone tz; + gettimeofday (&t,&tz); + return (1000*t.tv_sec)+(t.tv_usec/1000); +} + + +int main (int argc,char *params[]) +{ + int i,result; + long d=0; + long a1=0,a2=0; + long c1=0, c2=0; + unsigned long int start,mstart=0,lastcall=0; + + start = time_msec(); + + /* + Load parameters + If parameters are valid continue + */ + + if (read_param(argc,params)) + { + /* + Initialise USB system + and enable debug mode + + if ( debug ) + usb_set_debug(2); + */ + /* + Search the device + */ + if ( OpenDevice(ipid)<0 ) { + printf("Could not open the k8055 (port:%d)\nPlease ensure that the device is correctly connected.\n",ipid); + return (-1); + + } else { + + if ( resetcnt1 ) + ResetCounter(1); + if ( resetcnt2 ) + ResetCounter(2); + if ( dbt1 != -1 ) + SetCounterDebounceTime(1,dbt1); + if ( dbt2 != -1 ) + SetCounterDebounceTime(2,dbt1); + + if ((ia1!=-1) && (ia2!=-1) && (id8!=-1)) { + result = SetAllValues(id8,ia1,ia2); + if (debug) printf("SetAllValues=%d - Digital:%d, analog1:%d, analog2:%d\n",result,id8,ia1,ia2); + } + else if ((id8 != -1) && (ia1!=-1)) { + result = SetAllValues(id8,ia1,0); + if (debug) printf("SetAllValues=%d - Digital:%d, analog1:%d\n",result,id8,ia1); + } + else if ((id8 != -1) && (ia2!=-1)) { + result = SetAllValues(id8,0,ia2); + if (debug) printf("SetAllValues=%d - Digital:%d, analog2:%d\n",result,id8,ia2); + } + else if ((ia1 != -1) && (ia2!=-1)) { + result = SetAllValues(0,ia1,ia2); + if (debug) printf("SetAllValues=%d - analog1:%d, analog2:%d\n",result,ia1,ia2); + } + else { + if (ia1!=-1) { + result=OutputAnalogChannel(1,ia1); + if (debug) printf("Set analog1:%d=>%d\n",ia1,result); + } + if (ia2!=-1) { + result=OutputAnalogChannel(2,ia2); + if (debug) printf("Set analog2:%d=>%d\n",ia2,result); + } + if (id8!=-1) { + result=WriteAllDigital((long)id8); + if (debug) printf("Set digital:%d=>%d\n",id8,result); + } + } + + mstart = time_msec(); // Measure start + for (i=0; i<numread; i++) { + + if ( delay ) { + // Wait until next measure + while ( time_msec()-mstart < i*delay ); + } + ReadAllValues( &d,&a1,&a2,&c1,&c2); + +/* ReadAllAnalog(&a1,&a2); + d=ReadAllDigital(); + c1=ReadCounter(1); + c2=ReadCounter(2); +*/ + lastcall = time_msec(); + printf("%d;%d;%d;%d;%d;%d\n", (int)(lastcall-start),(int)d, (int)a1, (int)a2,(int)c1,(int)c2 ); + } + + CloseDevice(); + } + } + return 0; +} diff --git a/man/k8055.1.gz b/man/k8055.1.gz Binary files differnew file mode 100644 index 0000000..042fdf4 --- /dev/null +++ b/man/k8055.1.gz diff --git a/pyk8055/Makefile b/pyk8055/Makefile new file mode 100644 index 0000000..a2069d3 --- /dev/null +++ b/pyk8055/Makefile @@ -0,0 +1,37 @@ +# $Id: Makefile,v 1.3 2007/04/08 10:54:49 pjetur Exp $ +# +#cc = gcc +#pylibdir = pyk8055 +#libs = -lusb -L/usr/lib -lm + +# We have to build extension "inplace" if We're to +# run samples locally without installing + +all: libk8055.i ../libk8055.c + python setup.py build_ext --inplace + python setup.py build + +# Or in plain language +# swig -python libk8055.i +# cc -fpic -O2 -c ../libk8055.c -o ./libk8055.o +# cc -fpic -O2 -c libk8055_wrap.c -I /usr/include/python2.4/ -o libk8055_wrap.o +# ld -shared libk8055.o libk8055_wrap.o -lusb -o _pyk8055.so +## mv -f pyk8055.py __init__.py + +.PHONY: kdemo + +kdemo: k8055qt.py frmk8055qt.ui frmk8055qt.ui.h + pyuic frmk8055qt.ui -o frmk8055qt.py + +# install will both make build and install +install: + python setup.py install + +# Remove all swig generated files +clean: + python setup.py clean --all + rm -f *.o _pyk8055.so libk8055_wrap.c pyk8055.py pyk8055.pyc + +uninstall: + python setup.py uninstall + #rm -f /usr/lib/python-2.4/site-packages/pyk8055.py /usr/lib/python-2.4/site-packages/_pyk8055.so diff --git a/pyk8055/frmk8055qt.ui b/pyk8055/frmk8055qt.ui new file mode 100644 index 0000000..2669c01 --- /dev/null +++ b/pyk8055/frmk8055qt.ui @@ -0,0 +1,1422 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>K8055QT</class> +<comment>Python:#from kdecore import * +Python:from kdeui import * +Python:from pyk8055 import * +</comment> +<widget class="QDialog"> + <property name="name"> + <cstring>K8055QT</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>314</height> + </rect> + </property> + <property name="caption"> + <string>K8055 Status</string> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>OutputGroup</cstring> + </property> + <property name="geometry"> + <rect> + <x>320</x> + <y>70</y> + <width>270</width> + <height>51</height> + </rect> + </property> + <property name="title"> + <string>Digital Output</string> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>OutputBox5</cstring> + </property> + <property name="geometry"> + <rect> + <x>140</x> + <y>20</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>5</string> + </property> + <property name="toolTip" stdset="0"> + <string>Digital Output 5</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>OutputBox6</cstring> + </property> + <property name="geometry"> + <rect> + <x>169</x> + <y>20</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>6</string> + </property> + <property name="toolTip" stdset="0"> + <string>Digital Output 6</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>OutputBox7</cstring> + </property> + <property name="geometry"> + <rect> + <x>199</x> + <y>20</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>7</string> + </property> + <property name="toolTip" stdset="0"> + <string>Digital Output 7</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>OutputBox8</cstring> + </property> + <property name="geometry"> + <rect> + <x>229</x> + <y>20</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>8</string> + </property> + <property name="toolTip" stdset="0"> + <string>Digital Output 8</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>OutputBox1</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>20</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>1</string> + </property> + <property name="toolTip" stdset="0"> + <string>Digital Output 1</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>OutputBox2</cstring> + </property> + <property name="geometry"> + <rect> + <x>42</x> + <y>20</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>2</string> + </property> + <property name="toolTip" stdset="0"> + <string>Digital Output 2</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>OutputBox3</cstring> + </property> + <property name="geometry"> + <rect> + <x>76</x> + <y>20</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>3</string> + </property> + <property name="toolTip" stdset="0"> + <string>Digital Output 3</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>OutputBox4</cstring> + </property> + <property name="geometry"> + <rect> + <x>110</x> + <y>20</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>4</string> + </property> + <property name="toolTip" stdset="0"> + <string>Digital Output 4</string> + </property> + </widget> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>InputGroup</cstring> + </property> + <property name="geometry"> + <rect> + <x>320</x> + <y>130</y> + <width>270</width> + <height>70</height> + </rect> + </property> + <property name="title"> + <string>Digital Input</string> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>DigitaltextLabel1</cstring> + </property> + <property name="geometry"> + <rect> + <x>18</x> + <y>40</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>1</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>DigitaltextLabel4</cstring> + </property> + <property name="geometry"> + <rect> + <x>170</x> + <y>40</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>4</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>DigitaltextLabel5</cstring> + </property> + <property name="geometry"> + <rect> + <x>220</x> + <y>40</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>5</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>DigitaltextLabel2</cstring> + </property> + <property name="geometry"> + <rect> + <x>69</x> + <y>40</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>2</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>DigitaltextLabel3</cstring> + </property> + <property name="geometry"> + <rect> + <x>120</x> + <y>40</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>3</string> + </property> + <property name="alignment"> + <set>AlignCenter</set> + </property> + </widget> + <widget class="KLed"> + <property name="name"> + <cstring>DigitalLed1</cstring> + </property> + <property name="geometry"> + <rect> + <x>20</x> + <y>20</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="state"> + <enum>Off</enum> + </property> + <property name="color"> + <color> + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </property> + <property name="toolTip" stdset="0"> + <string>Digital 1 input state</string> + </property> + </widget> + <widget class="KLed"> + <property name="name"> + <cstring>DigitalLed2</cstring> + </property> + <property name="geometry"> + <rect> + <x>70</x> + <y>20</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="state"> + <enum>Off</enum> + </property> + <property name="color"> + <color> + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </property> + <property name="toolTip" stdset="0"> + <string>Digital 2 input state</string> + </property> + </widget> + <widget class="KLed"> + <property name="name"> + <cstring>DigitalLed3</cstring> + </property> + <property name="geometry"> + <rect> + <x>121</x> + <y>20</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="state"> + <enum>Off</enum> + </property> + <property name="color"> + <color> + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </property> + <property name="toolTip" stdset="0"> + <string>Digital 3 input state</string> + </property> + </widget> + <widget class="KLed"> + <property name="name"> + <cstring>DigitalLed4</cstring> + </property> + <property name="geometry"> + <rect> + <x>173</x> + <y>20</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="state"> + <enum>Off</enum> + </property> + <property name="color"> + <color> + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </property> + <property name="toolTip" stdset="0"> + <string>Digital 4 input state</string> + </property> + </widget> + <widget class="KLed"> + <property name="name"> + <cstring>DigitalLed5</cstring> + </property> + <property name="geometry"> + <rect> + <x>221</x> + <y>20</y> + <width>20</width> + <height>20</height> + </rect> + </property> + <property name="state"> + <enum>Off</enum> + </property> + <property name="color"> + <color> + <red>255</red> + <green>0</green> + <blue>0</blue> + </color> + </property> + <property name="toolTip" stdset="0"> + <string>Digital 5 input state</string> + </property> + </widget> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupCounter1</cstring> + </property> + <property name="geometry"> + <rect> + <x>320</x> + <y>200</y> + <width>271</width> + <height>51</height> + </rect> + </property> + <property name="title"> + <string>Counter 1</string> + </property> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>1 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>2 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>5 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>10 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>50 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>100 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>500 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>1000 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>2000 ms</string> + </property> + </item> + <property name="name"> + <cstring>comboCounter1</cstring> + </property> + <property name="geometry"> + <rect> + <x>171</x> + <y>20</y> + <width>90</width> + <height>21</height> + </rect> + </property> + <property name="toolTip" stdset="0"> + <string>Debounce value counter #1</string> + </property> + </widget> + <widget class="QLCDNumber"> + <property name="name"> + <cstring>Counter1Value</cstring> + </property> + <property name="geometry"> + <rect> + <x>20</x> + <y>20</y> + <width>71</width> + <height>21</height> + </rect> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="segmentStyle"> + <enum>Flat</enum> + </property> + <property name="toolTip" stdset="0"> + <string>Counter #1</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>ClearCounter1</cstring> + </property> + <property name="geometry"> + <rect> + <x>100</x> + <y>20</y> + <width>60</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>Reset</string> + </property> + <property name="toolTip" stdset="0"> + <string>Reset Counter #1</string> + </property> + </widget> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupCounter2</cstring> + </property> + <property name="geometry"> + <rect> + <x>320</x> + <y>250</y> + <width>271</width> + <height>51</height> + </rect> + </property> + <property name="title"> + <string>Counter 2</string> + </property> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>1 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>2 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>5 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>10 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>50 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>100 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>500 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>1000 ms</string> + </property> + </item> + <item> + <property name="text"> + <string>2000 ms</string> + </property> + </item> + <property name="name"> + <cstring>comboCounter2</cstring> + </property> + <property name="geometry"> + <rect> + <x>171</x> + <y>20</y> + <width>90</width> + <height>21</height> + </rect> + </property> + <property name="toolTip" stdset="0"> + <string>Debounce value counter #2</string> + </property> + </widget> + <widget class="QLCDNumber"> + <property name="name"> + <cstring>Counter2Value</cstring> + </property> + <property name="geometry"> + <rect> + <x>20</x> + <y>20</y> + <width>71</width> + <height>21</height> + </rect> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="segmentStyle"> + <enum>Flat</enum> + </property> + <property name="toolTip" stdset="0"> + <string>Counter #2</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>ClearCounter2</cstring> + </property> + <property name="geometry"> + <rect> + <x>100</x> + <y>20</y> + <width>60</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>Reset</string> + </property> + <property name="toolTip" stdset="0"> + <string>Reset Counter #2</string> + </property> + </widget> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupDigitalButtonBox</cstring> + </property> + <property name="geometry"> + <rect> + <x>200</x> + <y>10</y> + <width>110</width> + <height>90</height> + </rect> + </property> + <property name="title"> + <string>Digital</string> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>ClearAllDigitalButton</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>50</y> + <width>90</width> + <height>30</height> + </rect> + </property> + <property name="text"> + <string>Clear All</string> + </property> + <property name="toolTip" stdset="0"> + <string>Clear all digital outputs</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>SetAllDigitalButton</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>20</y> + <width>90</width> + <height>30</height> + </rect> + </property> + <property name="text"> + <string>Set All</string> + </property> + <property name="toolTip" stdset="0"> + <string>Set all digital outputs</string> + </property> + </widget> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupAnalogButtonBox</cstring> + </property> + <property name="geometry"> + <rect> + <x>200</x> + <y>110</y> + <width>110</width> + <height>90</height> + </rect> + </property> + <property name="title"> + <string>Analog</string> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>ClearAllAnalogButton</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>50</y> + <width>90</width> + <height>30</height> + </rect> + </property> + <property name="text"> + <string>Clear All</string> + </property> + <property name="toolTip" stdset="0"> + <string>Set all analog outputs low</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>SetAllAnalogButton</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>20</y> + <width>90</width> + <height>30</height> + </rect> + </property> + <property name="text"> + <string>Set All</string> + </property> + <property name="toolTip" stdset="0"> + <string>Set all analog outputs high</string> + </property> + </widget> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupTestButtonBox</cstring> + </property> + <property name="geometry"> + <rect> + <x>200</x> + <y>210</y> + <width>110</width> + <height>90</height> + </rect> + </property> + <property name="title"> + <string>Test</string> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>TestAnalogButton</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>50</y> + <width>90</width> + <height>30</height> + </rect> + </property> + <property name="text"> + <string>Analog</string> + </property> + <property name="toolTip" stdset="0"> + <string>Run analog tests</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>TestDigitalButton</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>20</y> + <width>90</width> + <height>30</height> + </rect> + </property> + <property name="text"> + <string>Digital</string> + </property> + <property name="toolTip" stdset="0"> + <string>Run digital output tests</string> + </property> + </widget> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBoxAD2</cstring> + </property> + <property name="geometry"> + <rect> + <x>140</x> + <y>10</y> + <width>45</width> + <height>290</height> + </rect> + </property> + <property name="title"> + <string>AD2</string> + </property> + <widget class="QScrollBar"> + <property name="name"> + <cstring>BarAD2</cstring> + </property> + <property name="geometry"> + <rect> + <x>16</x> + <y>20</y> + <width>20</width> + <height>230</height> + </rect> + </property> + <property name="maxValue"> + <number>255</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="toolTip" stdset="0"> + <string>Analog input value - AD2</string> + </property> + </widget> + <widget class="QLCDNumber"> + <property name="name"> + <cstring>AD2Value</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>260</y> + <width>30</width> + <height>20</height> + </rect> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="numDigits"> + <number>3</number> + </property> + <property name="segmentStyle"> + <enum>Flat</enum> + </property> + <property name="toolTip" stdset="0"> + <string>Analog value AD2</string> + </property> + </widget> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBoxAD1</cstring> + </property> + <property name="geometry"> + <rect> + <x>100</x> + <y>10</y> + <width>45</width> + <height>290</height> + </rect> + </property> + <property name="title"> + <string>AD1</string> + </property> + <widget class="QLCDNumber"> + <property name="name"> + <cstring>AD1Value</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>260</y> + <width>30</width> + <height>20</height> + </rect> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="numDigits"> + <number>3</number> + </property> + <property name="segmentStyle"> + <enum>Flat</enum> + </property> + <property name="toolTip" stdset="0"> + <string>Analog value AD1</string> + </property> + </widget> + <widget class="QScrollBar"> + <property name="name"> + <cstring>BarAD1</cstring> + </property> + <property name="geometry"> + <rect> + <x>15</x> + <y>20</y> + <width>20</width> + <height>230</height> + </rect> + </property> + <property name="maxValue"> + <number>255</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="toolTip" stdset="0"> + <string>Analog input value - AD1</string> + </property> + </widget> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBoxDA2</cstring> + </property> + <property name="geometry"> + <rect> + <x>55</x> + <y>10</y> + <width>45</width> + <height>290</height> + </rect> + </property> + <property name="title"> + <string>DA2</string> + </property> + <widget class="QLCDNumber"> + <property name="name"> + <cstring>DA2Value</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>260</y> + <width>30</width> + <height>20</height> + </rect> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="numDigits"> + <number>3</number> + </property> + <property name="segmentStyle"> + <enum>Flat</enum> + </property> + <property name="toolTip" stdset="0"> + <string>Analog value DA2</string> + </property> + </widget> + <widget class="QScrollBar"> + <property name="name"> + <cstring>BarDA2</cstring> + </property> + <property name="geometry"> + <rect> + <x>15</x> + <y>20</y> + <width>20</width> + <height>230</height> + </rect> + </property> + <property name="maxValue"> + <number>255</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="toolTip" stdset="0"> + <string>Analog output value - DA2</string> + </property> + </widget> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBoxDA1</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>45</width> + <height>290</height> + </rect> + </property> + <property name="title"> + <string>DA1</string> + </property> + <widget class="QLCDNumber"> + <property name="name"> + <cstring>DA1Value</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>260</y> + <width>30</width> + <height>20</height> + </rect> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="numDigits"> + <number>3</number> + </property> + <property name="segmentStyle"> + <enum>Flat</enum> + </property> + <property name="toolTip" stdset="0"> + <string>Analog value DA1</string> + </property> + </widget> + <widget class="QScrollBar"> + <property name="name"> + <cstring>BarDA1</cstring> + </property> + <property name="geometry"> + <rect> + <x>15</x> + <y>20</y> + <width>20</width> + <height>230</height> + </rect> + </property> + <property name="maxValue"> + <number>255</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="toolTip" stdset="0"> + <string>Analog output value - DA1</string> + </property> + </widget> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupCard</cstring> + </property> + <property name="geometry"> + <rect> + <x>320</x> + <y>10</y> + <width>271</width> + <height>51</height> + </rect> + </property> + <property name="title"> + <string>Card</string> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>CardRadioGroup</cstring> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>19</y> + <width>151</width> + <height>20</height> + </rect> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="title"> + <string></string> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>CardButton1</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>1</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Select Card #1</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>CardButton3</cstring> + </property> + <property name="geometry"> + <rect> + <x>80</x> + <y>0</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>3</string> + </property> + <property name="toolTip" stdset="0"> + <string>Select Card #3</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>CardButton2</cstring> + </property> + <property name="geometry"> + <rect> + <x>40</x> + <y>0</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>2</string> + </property> + <property name="toolTip" stdset="0"> + <string>Select Card #2</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>CardButton4</cstring> + </property> + <property name="geometry"> + <rect> + <x>120</x> + <y>0</y> + <width>30</width> + <height>21</height> + </rect> + </property> + <property name="text"> + <string>4</string> + </property> + <property name="toolTip" stdset="0"> + <string>Select Card #4</string> + </property> + </widget> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>ConnectButton</cstring> + </property> + <property name="geometry"> + <rect> + <x>179</x> + <y>15</y> + <width>80</width> + <height>30</height> + </rect> + </property> + <property name="text"> + <string>Connect</string> + </property> + <property name="toolTip" stdset="0"> + <string>Connect to selected card</string> + </property> + </widget> + </widget> +</widget> +<connections> + <connection> + <sender>ConnectButton</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>ConnectButton_clicked()</slot> + </connection> + <connection> + <sender>CardButton1</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>CardButton1_clicked()</slot> + </connection> + <connection> + <sender>CardButton2</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>CardButton2_clicked()</slot> + </connection> + <connection> + <sender>ClearCounter2</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>ClearCounter2_clicked()</slot> + </connection> + <connection> + <sender>OutputBox1</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>OutputBox1_clicked()</slot> + </connection> + <connection> + <sender>ClearCounter1</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>ClearCounter1_clicked()</slot> + </connection> + <connection> + <sender>OutputBox8</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>OutputBox8_clicked()</slot> + </connection> + <connection> + <sender>OutputBox7</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>OutputBox7_clicked()</slot> + </connection> + <connection> + <sender>OutputBox2</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>OutputBox2_clicked()</slot> + </connection> + <connection> + <sender>OutputBox3</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>OutputBox3_clicked()</slot> + </connection> + <connection> + <sender>OutputBox4</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>OutputBox4_clicked()</slot> + </connection> + <connection> + <sender>OutputBox5</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>OutputBox5_clicked()</slot> + </connection> + <connection> + <sender>OutputBox6</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>OutputBox6_clicked()</slot> + </connection> + <connection> + <sender>SetAllAnalogButton</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>SetAllAnalogButton_clicked()</slot> + </connection> + <connection> + <sender>ClearAllAnalogButton</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>ClearAllAnalogButton_clicked()</slot> + </connection> + <connection> + <sender>SetAllDigitalButton</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>SetAllDigitalButton_clicked()</slot> + </connection> + <connection> + <sender>ClearAllDigitalButton</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>ClearAllDigitalButton_clicked()</slot> + </connection> + <connection> + <sender>BarAD2</sender> + <signal>valueChanged(int)</signal> + <receiver>K8055QT</receiver> + <slot>BarAD2_valueChanged(int)</slot> + </connection> + <connection> + <sender>BarAD1</sender> + <signal>valueChanged(int)</signal> + <receiver>K8055QT</receiver> + <slot>BarAD1_valueChanged(int)</slot> + </connection> + <connection> + <sender>comboCounter2</sender> + <signal>activated(int)</signal> + <receiver>K8055QT</receiver> + <slot>comboCounter2_activated(int)</slot> + </connection> + <connection> + <sender>comboCounter1</sender> + <signal>activated(int)</signal> + <receiver>K8055QT</receiver> + <slot>comboCounter1_activated(int)</slot> + </connection> + <connection> + <sender>TestDigitalButton</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>TestDigitalButton_clicked()</slot> + </connection> + <connection> + <sender>TestAnalogButton</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>TestAnalogButton_clicked()</slot> + </connection> + <connection> + <sender>CardButton3</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>CardButton3_clicked()</slot> + </connection> + <connection> + <sender>CardButton4</sender> + <signal>clicked()</signal> + <receiver>K8055QT</receiver> + <slot>CardButton4_clicked()</slot> + </connection> +</connections> +<includes> + <include location="local" impldecl="in implementation">frmk8055qt.ui.h</include> +</includes> +<variables> + <variable access="private">Kpriv;</variable> + <variable access="public">Kp = False;</variable> +</variables> +<slots> + <slot>ConnectButton_clicked()</slot> + <slot>CardButton1_clicked()</slot> + <slot>CardButton2_clicked()</slot> + <slot>CardButton3_clicked()</slot> + <slot>CardButton4_clicked()</slot> + <slot>init()</slot> + <slot>ClearCounter1_clicked()</slot> + <slot>ClearCounter2_clicked()</slot> + <slot>OutputBox1_clicked()</slot> + <slot>OutputBox2_clicked()</slot> + <slot>OutputBox3_clicked()</slot> + <slot>OutputBox4_clicked()</slot> + <slot>OutputBox5_clicked()</slot> + <slot>OutputBox6_clicked()</slot> + <slot>OutputBox7_clicked()</slot> + <slot>OutputBox8_clicked()</slot> + <slot>SetAllAnalogButton_clicked()</slot> + <slot>ClearAllAnalogButton_clicked()</slot> + <slot>SetAllDigitalButton_clicked()</slot> + <slot>ClearAllDigitalButton_clicked()</slot> + <slot>BarAD1_valueChanged( int )</slot> + <slot>BarAD2_valueChanged( int )</slot> + <slot>comboCounter2_activated( int )</slot> + <slot>comboCounter1_activated( int )</slot> + <slot>TestDigitalButton_clicked()</slot> + <slot>TestAnalogButton_clicked()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kled.h</includehint> + <includehint>kled.h</includehint> + <includehint>kled.h</includehint> + <includehint>kled.h</includehint> + <includehint>kled.h</includehint> +</includehints> +</UI> diff --git a/pyk8055/frmk8055qt.ui.h b/pyk8055/frmk8055qt.ui.h new file mode 100644 index 0000000..1e986e6 --- /dev/null +++ b/pyk8055/frmk8055qt.ui.h @@ -0,0 +1,260 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you want to add, delete, or rename functions or slots, use +** Qt Designer to update this file, preserving your code. +** +** You should not define a constructor or destructor in this file. +** Instead, write your code in functions called init() and destroy(). +** These will automatically be called by the form's constructor and +** destructor. +*****************************************************************************/ + + +void K8055QT::ConnectButton_clicked() +{ + if (self.card != None) and (self.k == None): + try: + #print "Connect to card #",self.card + self.k = k8055(self.card) + self.EnableAll() + self.ClearAllDigitalButton_clicked() + self.ClearAllAnalogButton_clicked() + self.comboCounter1.setCurrentItem(0) + self.comboCounter2.setCurrentItem(0) + + self.ConnectButton.setText(self.__tr("Disconnect")) + except: + print "No such Card" + elif (self.k != None): + try: + #print "Disconnect from card #",self.card + self.k.CloseDevice() + self.k = None + self.DisableAll() + self.OutputBox1.setChecked(0) + self.OutputBox2.setChecked(0) + self.OutputBox3.setChecked(0) + self.OutputBox4.setChecked(0) + self.OutputBox5.setChecked(0) + self.OutputBox6.setChecked(0) + self.OutputBox7.setChecked(0) + self.OutputBox8.setChecked(0) + self.BarDA1.setValue(0) + self.BarDA2.setValue(0) + self.BarAD1.setValue(0) + self.BarAD2.setValue(0) + self.DA1Value.setProperty("intValue",QVariant(0)) + self.DA2Value.setProperty("intValue",QVariant(0)) + self.AD1Value.setProperty("intValue",QVariant(0)) + self.AD2Value.setProperty("intValue",QVariant(0)) + self.comboCounter1.setCurrentItem(0) + self.comboCounter2.setCurrentItem(0) + self.Counter1Value.setProperty("intValue",QVariant(0)) + self.Counter2Value.setProperty("intValue",QVariant(0)) + self.ConnectButton.setText(self.__tr("Connect")) + except: + pass + +} + + +void K8055QT::CardButton1_clicked() +{ + self.card = 0 +} + +void K8055QT::CardButton2_clicked() +{ + self.card = 1 +} + +void K8055QT::CardButton3_clicked() +{ + self.card = 2 +} + +void K8055QT::CardButton4_clicked() +{ + self.card = 3 +} + + +void K8055QT::init() +{ + self.k = None + self.DisableAll() +} + +void K8055QT::ClearCounter1_clicked() +{ + if self.k: + self.k.ResetCounter(1) +} + +void K8055QT::ClearCounter2_clicked() +{ + if self.k: + self.k.ResetCounter(2) +} + + +void K8055QT::OutputBox1_clicked() +{ + if self.k: + if self.OutputBox1.isChecked(): + self.k.SetDigitalChannel(1) + else: + self.k.ClearDigitalChannel(1) +} + +void K8055QT::OutputBox2_clicked() +{ + if self.k: + if self.OutputBox2.isChecked(): + self.k.SetDigitalChannel(2) + else: + self.k.ClearDigitalChannel(2) + +void K8055QT::OutputBox3_clicked() +{ + if self.k: + if self.OutputBox3.isChecked(): + self.k.SetDigitalChannel(3) + else: + self.k.ClearDigitalChannel(3) +} +void K8055QT::OutputBox4_clicked() +{ + if self.k: + if self.OutputBox4.isChecked(): + self.k.SetDigitalChannel(4) + else: + self.k.ClearDigitalChannel(4) +} +void K8055QT::OutputBox5_clicked() +{ + if self.k: + if self.OutputBox5.isChecked(): + self.k.SetDigitalChannel(5) + else: + self.k.ClearDigitalChannel(5) +} +void K8055QT::OutputBox6_clicked() +{ + if self.k: + if self.OutputBox6.isChecked(): + self.k.SetDigitalChannel(6) + else: + self.k.ClearDigitalChannel(6) +} +void K8055QT::OutputBox7_clicked() +{ + if self.k: + if self.OutputBox7.isChecked(): + self.k.SetDigitalChannel(7) + else: + self.k.ClearDigitalChannel(7) +} +void K8055QT::OutputBox8_clicked() +{ + if self.k: + if self.OutputBox8.isChecked(): + self.k.SetDigitalChannel(8) + else: + self.k.ClearDigitalChannel(8) +} + + +void K8055QT::SetAllAnalogButton_clicked() +{ + if self.k: + self.k.SetAllAnalog() + self.BarAD1.setValue(0) + self.BarAD2.setValue(0) + self.AD1Value.setProperty("intValue",QVariant(255)) + self.AD2Value.setProperty("intValue",QVariant(255)) +} + + +void K8055QT::ClearAllAnalogButton_clicked() +{ + if self.k: + self.k.ClearAllAnalog() + self.BarAD1.setValue(255) + self.BarAD2.setValue(255) + self.AD1Value.setProperty("intValue",QVariant(0)) + self.AD2Value.setProperty("intValue",QVariant(0)) +} + + +void K8055QT::SetAllDigitalButton_clicked() +{ + if self.k: + self.k.SetAllDigital() + self.OutputBox1.setChecked(1) + self.OutputBox2.setChecked(1) + self.OutputBox3.setChecked(1) + self.OutputBox4.setChecked(1) + self.OutputBox5.setChecked(1) + self.OutputBox6.setChecked(1) + self.OutputBox7.setChecked(1) + self.OutputBox8.setChecked(1) +} + +void K8055QT::ClearAllDigitalButton_clicked() +{ + if self.k: + self.k.ClearAllDigital() + self.OutputBox1.setChecked(0) + self.OutputBox2.setChecked(0) + self.OutputBox3.setChecked(0) + self.OutputBox4.setChecked(0) + self.OutputBox5.setChecked(0) + self.OutputBox6.setChecked(0) + self.OutputBox7.setChecked(0) + self.OutputBox8.setChecked(0) +} + + +void K8055QT::BarAD1_valueChanged( int ) +{ + if self.k: + self.k.OutputAnalogChannel(1,255-a0) + self.AD1Value.setProperty("intValue",QVariant(255-a0)) +} + +void K8055QT::BarAD2_valueChanged( int ) +{ + if self.k: + self.k.OutputAnalogChannel(2,255-a0) + self.AD2Value.setProperty("intValue",QVariant(255-a0)) +} + + +void K8055QT::comboCounter2_activated( int ) +{ + if self.k: + v = str(self.comboCounter2.currentText()).split() + self.k.SetCounterDebounceTime(2,int(v[0])) +} + + +void K8055QT::comboCounter1_activated( int ) +{ + if self.k: + v = str(self.comboCounter1.currentText()).split() + self.k.SetCounterDebounceTime(1,int(v[0])) +} + + +void K8055QT::TestDigitalButton_clicked() +{ + self.DigitalTest() +} + + +void K8055QT::TestAnalogButton_clicked() +{ + self.AnalogTest() +} diff --git a/pyk8055/k8055.py b/pyk8055/k8055.py new file mode 100755 index 0000000..3c03a10 --- /dev/null +++ b/pyk8055/k8055.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python +# $Id: k8055.py,v 1.2 2007/03/15 14:50:55 pjetur Exp $ +""" +Python version of K8055 command line program + +Copyright (C) 2007 by Pjetur G. Hjaltason + +Syntax : python k8055.py [-p:(number)] [-d:(value)] [-a1:(value)] [-a2:(value)] + [-num:(number) [-delay:(number)] [-dbt1:(value)] + [-dbt2:(value)] [-reset1] [-reset2] [-debug] [-h|--help] + -p:(number) Set board number (0/1/2/3) + -d:(value) Set digital output value (bitmask, 8 bits in decimal) + -a1:(value) Set analog output 1 value (0-255) + -a2:(value) Set analog output 2 value (0-255) + -num:(number) Set number of measures (-1 for no read) + -delay:(number) Set delay between two measures (in msec) + -dbt1:(value) Set debounce time for counter 1 (in msec) + -dbt2:(value) Set debounce time for counter 2 (in msec) + -reset1 Reset counter 1 + -reset2 Reset counter 2 + -debug Activate debug mode + -h or --help Print this text + +Example : python k8055.py -p:1 -d:147 -a1:25 -a2:203 + +NOTE: + Because of the nature of commands sent to the K8055 board, this + program has no way of knowing previous state of the analog or + digial outputs, thus each run of this command will clear the previous + state - and set a new state - of the analog and digital outputs + + See header of libk8055.c for more details of K8055 commands +""" +import sys +from time import sleep, time +from pyk8055 import * + +def main(argv): + # preset values + p , db = 0,0 # Port, debug + r1, r2 = 0,0 # reset1, reset2 + dl = -1 # delay + db1,db2 = -1,-1 # debounce1, debounce2 + a1,a2,d = -1,-1,-1 # analog1, analog2, digital + nm = 1 # number of times to read, default once + + # not the standard getopts way, but... + for arg in argv: + if arg in ("-h", "--help"): + print __doc__ + sys.exit(0) + elif arg[:4] == "-a1:" : a1 = int(arg[4:]) + elif arg[:4] == "-a2:" : a2 = int(arg[4:]) + elif arg[:5] == "-num:" : nm = int(arg[5:]) + elif arg[:3] == "-d:" : d = int(arg[3:]) + elif arg[:3] == "-p:" : p = int(arg[3:]) + elif arg[:7] == "-delay:" : dl = int(arg[7:]) + elif arg[:6] == "-dbt1:" : db1 = int(arg[6:]) + elif arg[:6] == "-dbt2:" : db2 = int(arg[6:]) + elif arg == "-reset1" : r1 = 1 + elif arg == "-reset2" : r2 = 1 + elif arg == "-debug" : db = 1 + else: + print __doc__ + sys.exit(0) + + try: + # Open device + if db == 1: k = k8055(p,True) # Debug mode + else: k = k8055(p) + + # set requested + if r1 != 0: k.ResetCounter(1) + if r2 != 0: k.ResetCounter(2) + if db1 != -1: k.SetCounterDebounceTime(1, db1) + if db2 != -1: k.SetCounterDebounceTime(2, db2) + + # Try to set all digital/analog values at the same time + if (d != -1 and a1 != -1 and a2 != -1) : SetAllValues(d,a1,a2) + elif (d != -1 and a1 != -1 ) : SetAllValues(d,a1,0) + elif (d != -1 and a2 != -1 ) : SetAllValues(d,0,a2) + elif (a1 != -1 and a2 != -1 ) : SetAllValues(0,a1,a2) + # Else only one specified + else: + if d != -1: k.WriteAllDigital(d) + if a1 != -1: k.OutputAnalogChannel(1,a1) + if a2 != -1: k.OutputAnalogChannel(2,a2) + + # Now we loop (or not) for the specified number of times + # reading all the input values + + # Each read of all values will take about 2-8ms, at least + # on my setup - so no sense in using delay less than 10 + if (dl > 0) & (dl < 10): dl = 10 + + if (nm > 0) & (dl > 0): + tst = tstart = time() + i = 0 + while nm > 0: + ds = str(k) + tnow = time() + tms = (tnow - tstart) * 1000.0 + delta= dl - (tms - dl*i) + #tst = tnow + print str(int(tms+0.4999))+";"+ds + sleep((delta)/1000.0) # compensate for read time + nm -= 1 + i += 1 + elif nm > 0: + print "0;"+ str(k) + + k.CloseDevice() + + except IOError: + print "Could not open the k8055 (port:%s)" % str(p) + +main(sys.argv[1:]) diff --git a/pyk8055/k8055qt.png b/pyk8055/k8055qt.png Binary files differnew file mode 100644 index 0000000..85647db --- /dev/null +++ b/pyk8055/k8055qt.png diff --git a/pyk8055/k8055qt.py b/pyk8055/k8055qt.py new file mode 100644 index 0000000..49288f6 --- /dev/null +++ b/pyk8055/k8055qt.py @@ -0,0 +1,232 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Python version of libK8055 demo program +# +# Copyright (C) 2007 by Pjetur G. Hjaltason +# + +import sys +from qt import * +#from qwt import * + +import time, string +from pyk8055 import * +from frmk8055qt import * + +class QTK8055(K8055QT): + def __init__(self): + K8055QT.__init__(self) + + # Not much sense in making a fancy menu yet + # + #puProg = QPopupMenu(self) + #puProg.insertItem("Quit", Kapp.quit) + + #puHelp = QPopupMenu(self) + #puHelp.insertItem("About", self.about) + + #self.menu = QMenuBar(self) + #self.menu.insertItem("Program", puProg) + #self.menu.insertItem("Help", puHelp) + + # enumerate devices + BMask = SearchDevices() + if not BMask: + print "No K8055 devices found" + exit + + # Enable those present + self.CardButton1.setEnabled((BMask & 0x01) > 0) + self.CardButton2.setEnabled((BMask & 0x02) > 0) + self.CardButton3.setEnabled((BMask & 0x04) > 0) + self.CardButton4.setEnabled((BMask & 0x08) > 0) + + # set the first one found as suggestion + if (BMask & 0x01) > 0: + self.card = 0 + self.CardButton1.setChecked(1) + elif (BMask & 0x02) > 0: + self.card = 1 + self.CardButton2.setChecked(1) + elif (BMask & 0x04) > 0: + self.card = 2 + self.CardButton3.setChecked(1) + elif (BMask & 0x08) > 0: + self.card = 3 + self.CardButton4.setChecked(1) + + self.time = QTime.currentTime() # get current time + internalTimer = QTimer( self ) # create internal timer + self.connect( internalTimer, SIGNAL("timeout()"), self.timeout ) + internalTimer.start( 100 ) # emit signal every 1/10 second + + self.timeout() + + def AnalogTest(self): + try: + for step in range(0,255,10): + self.BarAD1.setValue(step) + self.BarAD2.setValue(step) + time.sleep(0.1) + # set analog output channel 1 to 200/255*5v = 3.9V + for step in range(255,0,10): + self.BarAD1.setValue(step) + self.BarAD2.setValue(step) + time.sleep(0.1) + + # read both analog inputs + # note: this returns a list + #res = self.k.ReadAllAnalog() + #sres = res[1:] + + # There should be more interesting information in the messagebox ;-/ + + QMessageBox.information( self,'Information', "AllOK","Ok") + except: + pass + + def DigitalTest(self): + try: + # Create a rotating display of digital outputs + # while waiting for keypress on digital input 1 + # (longer than .2sec :) Loop at most 3 times + Input1High = False + for i in range(1,3): + d = 1 + self.k.WriteAllDigital(1) + while Input1High == False and d < 128: + Input1High = (self.k.ReadDigitalChannel(1) > 0) + if Input1High: break + time.sleep(0.2) # wait .2 sec + d *=2 # and continue rotating digital outputs + #if d > 128: d=1; + self.k.WriteAllDigital(d) + if Input1High: break + + res = "Digital input 1=" + str(self.k.ReadDigitalChannel(1)) + "<br>" + # read the counter on input 1 + res+= "Counter(1)=" + str(self.k.ReadCounter(1)) + "<br>" + # read the counter on input 2 + res+= "Counter(2)=" + str(self.k.ReadCounter(2)) + + # set even bits on digital outputs + self.k.WriteAllDigital(170) + time.sleep(1) + # set odd bits on digital outputs + self.k.WriteAllDigital(85) + time.sleep(1) + # Clear all digital outputs + self.k.WriteAllDigital(0) + + # There should be more interesting information in the messagebox ;-/ + + QMessageBox.information( self,'DigitalTest', res,"Ok") + except: + QMessageBox.warning( self,'DigitalTest', "Not OK","Ok") + pass + + def EnableAll(self): + self.OutputBox1.setEnabled(1) + self.OutputBox2.setEnabled(1) + self.OutputBox3.setEnabled(1) + self.OutputBox4.setEnabled(1) + self.OutputBox5.setEnabled(1) + self.OutputBox6.setEnabled(1) + self.OutputBox7.setEnabled(1) + self.OutputBox8.setEnabled(1) + self.SetAllDigitalButton.setEnabled(1) + self.ClearAllDigitalButton.setEnabled(1) + self.SetAllAnalogButton.setEnabled(1) + self.ClearAllAnalogButton.setEnabled(1) + self.comboCounter1.setEnabled(1) + self.comboCounter2.setEnabled(1) + self.ClearCounter1.setEnabled(1) + self.ClearCounter2.setEnabled(1) + self.TestDigitalButton.setEnabled(1) + self.TestAnalogButton.setEnabled(1) + self.BarAD1.setEnabled(1) + self.BarAD2.setEnabled(1) + self.BarDA1.setEnabled(1) + self.BarDA2.setEnabled(1) + + def DisableAll(self): + self.OutputBox1.setEnabled(0) + self.OutputBox2.setEnabled(0) + self.OutputBox3.setEnabled(0) + self.OutputBox4.setEnabled(0) + self.OutputBox5.setEnabled(0) + self.OutputBox6.setEnabled(0) + self.OutputBox7.setEnabled(0) + self.OutputBox8.setEnabled(0) + self.SetAllDigitalButton.setEnabled(0) + self.ClearAllDigitalButton.setEnabled(0) + self.SetAllAnalogButton.setEnabled(0) + self.ClearAllAnalogButton.setEnabled(0) + self.comboCounter1.setEnabled(0) + self.comboCounter2.setEnabled(0) + self.ClearCounter1.setEnabled(0) + self.ClearCounter2.setEnabled(0) + self.TestDigitalButton.setEnabled(0) + self.TestAnalogButton.setEnabled(0) + self.BarAD1.setEnabled(0) + self.BarAD2.setEnabled(0) + self.BarDA1.setEnabled(0) + self.BarDA2.setEnabled(0) +# +## The QTimer::timeout() signal is received by this slot. +# + + def timeout( self ): + #new_time = QTime.currentTime() # get the current time + if self.k != None: + try: + AllVal = self.k.ReadAllValues() + #print AllVal,AllVal[2] + self.BarDA1.setValue(255 - AllVal[2]) + self.BarDA2.setValue(255 - AllVal[3]) + self.DA1Value.setProperty("intValue",QVariant(AllVal[2])) + self.DA2Value.setProperty("intValue",QVariant(AllVal[3])) + self.Counter1Value.setProperty("intValue",QVariant(AllVal[4])) + self.Counter2Value.setProperty("intValue",QVariant(AllVal[5])) + + if (AllVal[1] & 0x01) > 0: + self.DigitalLed1.setState(KLed.On) + else: + self.DigitalLed1.setState(KLed.Off) + if (AllVal[1] & 0x02) > 0: + self.DigitalLed2.setState(KLed.On) + else: + self.DigitalLed2.setState(KLed.Off) + if (AllVal[1] & 0x04) > 0: + self.DigitalLed3.setState(KLed.On) + else: + self.DigitalLed3.setState(KLed.Off) + if (AllVal[1] & 0x08) > 0: + self.DigitalLed4.setState(KLed.On) + else: + self.DigitalLed4.setState(KLed.Off) + if (AllVal[1] & 0x10) > 0: + self.DigitalLed5.setState(KLed.On) + else: + self.DigitalLed5.setState(KLed.Off) + except: + print "K8055 Read failed" + + def about(self): + QMessageBox.about( self, "About k8055qt", + "k8055qt is a small GUI program using libk8055\n\n" + "Copyright 2007 Pjetur G. Hjaltason. " + "Distributed under GPL license\n\n" + "For technical support, study the source code or surf\n" + "http://sourceforge.net/projects/libk8055/\n" ) + +if __name__ == "__main__": + Kapp = QApplication(sys.argv) + QObject.connect(Kapp,SIGNAL("lastWindowClosed()"),Kapp,SLOT("quit()")) + w = QTK8055() + Kapp.setMainWidget(w) + w.show() + Kapp.exec_loop() + + diff --git a/pyk8055/k8055test.py b/pyk8055/k8055test.py new file mode 100755 index 0000000..db5ee54 --- /dev/null +++ b/pyk8055/k8055test.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# $Id: k8055test.py,v 1.3 2007/03/28 10:09:34 pjetur Exp $ +# +# Sample pyton test program for pyk8055 wrapper +# Testing single board +# +from time import sleep +from pyk8055 import * + +try: + # CHANGE PORT HERE IF NEEDED + # Open device port 0 + k = k8055(0) + + # set analog output channel 1 to 200/255*5v = 3.9V + k.OutputAnalogChannel(1,200) + sleep(1) + # set analog output channel low again = 0V + k.OutputAnalogChannel(1,0) + + # read both analog inputs + # note: this returns a list + res = k.ReadAllAnalog() + print res[1:] + + # Test class string function + print str(k) + + # Set debounce time on counter 1 + k.SetCounterDebounceTime(1, 100) + + # reset counter 1 + k.ResetCounter(1) + + # create a rotating display of digital outputs + # while waiting for keypress on digital input 1 + # (longer than .2sec :) + Loop,dInput1,d = 0,0,1 + k.WriteAllDigital(1) + while Loop < 3 or dInput1 == 0: # is key 1 down (input 1 high) + dInput1 = k.ReadDigitalChannel(1) + Loop += 1 + sleep(0.2) # wait .2 sec + d *=2 # and continue rotating digital outputs + if d > 128: d=1; + k.WriteAllDigital(d) + + print "Digital input 1=",dInput1 + + # read the counter on input 1 + print "Counter(1)=",k.ReadCounter(1) + # read the counter on input 2 + print "Counter(2)=",k.ReadCounter(2) + + # set even bits on digital outputs + k.WriteAllDigital(170) + sleep(1) + # set odd bits on digital outputs + k.WriteAllDigital(85) + sleep(1) + # Clear all digital outputs + k.WriteAllDigital(0) + + # and close + k.CloseDevice() + +except IOError: + print "Could not open Device" + + diff --git a/pyk8055/k8055testm.py b/pyk8055/k8055testm.py new file mode 100644 index 0000000..a20dc30 --- /dev/null +++ b/pyk8055/k8055testm.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# $Id: k8055testm.py,v 1.1 2007/03/28 10:10:32 pjetur Exp $ +# +# Sample pyton test program for pyk8055 wrapper +# Scanning and testing multiple boards +# +from time import sleep +from pyk8055 import * + +try: + K8055_devices =[] + BMask = SearchDevices() + if not BMask: + print "No K8055 devices found" + exit + + if BMask & 0x01 : K8055_devices.append(k8055(0)) + if BMask & 0x02 : K8055_devices.append(k8055(1)) + if BMask & 0x04 : K8055_devices.append(k8055(2)) + if BMask & 0x08 : K8055_devices.append(k8055(3)) + + for k in K8055_devices: + k.SetCurrentDevice() + # set analog output channel 1 to 200/255*5v = 3.9V + k.OutputAnalogChannel(1,200) + sleep(1) + # set analog output channel low again = 0V + k.OutputAnalogChannel(1,0) + + # read both analog inputs + # note: this returns a list + res = k.ReadAllAnalog() + print "Analog status, board #",k.DeviceAddress(),res[1:] + + # Test class string function + print "Status, board #",k.DeviceAddress(),str(k) + + # Set debounce time on counter 1 + k.SetCounterDebounceTime(1, 100) + + # reset counter 1 + k.ResetCounter(1) + + # Loop creating a rotating display of digital outputs + # Loop 3 times + for i in range(1,3): + for k in K8055_devices: + k.SetCurrentDevice() + d = 1 + k.WriteAllDigital(1) + while d <= 128: # While this running + if k.ReadDigitalChannel(1): + print "Hello world (from board #%d)" %(k.DeviceAddress(),) + sleep(0.2) # wait .2 sec + d *=2 # and continue rotating digital outputs + k.WriteAllDigital(d) + + for k in K8055_devices: + k.SetCurrentDevice() + # read/print the counter on input 1 + print "Board # %d Counter #1=%d" % (k.DeviceAddress(),k.ReadCounter(1)) + # read/print the counter on input 2 + print "Board # %d Counter #2=%d" % (k.DeviceAddress(),k.ReadCounter(2)) + + for k in K8055_devices: + k.SetCurrentDevice() + # set even bits on digital outputs + k.WriteAllDigital(170) + + sleep(1) + + for k in K8055_devices: + k.SetCurrentDevice() + # set odd bits on digital outputs + k.WriteAllDigital(85) + + sleep(1) + + for k in K8055_devices: + k.SetCurrentDevice() + # Clear all digital outputs + k.WriteAllDigital(0) + + # and close + for k in K8055_devices: + k.SetCurrentDevice() + k.CloseDevice() + +except KeyboardInterrupt: + for k in K8055_devices: + k.SetCurrentDevice() + k.WriteAllDigital(0) + k.CloseDevice() + exit + +except IOError: + print "Could not open Device" + diff --git a/pyk8055/libk8055.i b/pyk8055/libk8055.i new file mode 100644 index 0000000..b0d31e9 --- /dev/null +++ b/pyk8055/libk8055.i @@ -0,0 +1,352 @@ +/* $Id: libk8055.i,v 1.3 2007/03/28 10:08:13 pjetur Exp $ + + Copyright (C) 2007 by Pjetur G. Hjaltason + + + Python wrapper for the libk8055 library using "swig" + This file is part of the libk8055 Library. + + The libk8055 Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The libk8055 Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + http://opensource.org/licenses/ + +*/ +%module pyk8055 +%include "typemaps.i" + +/* for the ReadAllAnalog and ReadAllValues function */ +%apply long *OUTPUT { long int *data1, long int *data2, long int *data3, long int *data4, long int *data5 }; + +%inline %{ + +/* For direct access to the DEBUG variable and global IO strings */ +extern int DEBUG; +extern unsigned char data_in[9]; +extern unsigned char data_out[9]; +/* + Extended functions for debugging the IO +*/ + +char strval[30]; + +/* returns 16byte hex string - 8 bytes */ +char * RawInput() + { + int i; + for(i=0; i< 8; i++) { + sprintf((char *)&strval[i*2],"%02X",data_in[i]); + } + return (char *)strval; + } + +/* More print friendly format */ +char * DumpInput() + { + int i; + for(i=0; i< 8; i++) { + sprintf((char *)&strval[i*3],"%02X:",data_in[i]); + } + strval[23] = '\0'; + return (char *)strval; + } + +char * DumpOutput() + { + int i; + for(i=0; i< 8; i++) { + sprintf((char *)&strval[i*3],"%02X:",data_out[i]); + } + strval[23] = '\0'; + return (char *)strval; + } +%} + +%{ +extern int OpenDevice (long int BoardAddress); +extern int CloseDevice (void); +extern long int ReadAnalogChannel (long int Channelno); +extern int ReadAllAnalog (long int *data1, long int *data2); +extern int OutputAnalogChannel (long int Channel, long int data); +extern int OutputAllAnalog (long int data1, long int data2); +extern int ClearAllAnalog (void); +extern int ClearAnalogChannel (long int Channel); +extern int SetAnalogChannel (long int Channel); +extern int SetAllAnalog (void); +extern int WriteAllDigital (long int data); +extern int ClearDigitalChannel (long int Channel); +extern int ClearAllDigital (void); +extern int SetDigitalChannel (long int Channel); +extern int SetAllDigital (void); +extern int ReadDigitalChannel (long int Channel); +extern long int ReadAllDigital (void); +extern int ResetCounter (long int counternr); +extern long int ReadCounter (long int CounterNo); +extern int SetCounterDebounceTime (long int CounterNo, long int DebounceTime); +extern int ReadAllValues (long int *data1, long int *data2, long int *data3, long int *data4, long int *data5); +extern int SetAllValues(int digitaldata, int addata1, int addata2); +extern int SetCounterDebounceTime(long CounterNo, long DebounceTime); +extern long SetCurrentDevice(long deviceno); +extern long SearchDevices(void); +extern char *Version(void); + +%} +/* + +And here we create the class interface to the library + +*/ +%pythoncode %{ +K8055_ERROR = -1 +_K8055_CLOSED = -1 + +class k8055: + "Class interface to the libk8055 library" + def __init__(self,BoardAddress=None,debug=False): + """Constructor, optional board open + + k=k8055() # Does not connect to board + k=k8055(1) # Init class and connect to board 1 + k=k8055(1,True) # connect to board 0 and enable debugging + + """ + self.Buttons = 0 + self.dev = _K8055_CLOSED + self.Address = BoardAddress + if debug == False: + self.DebugOff() + else: + self.DebugOn() + if BoardAddress != None: + try: + self.dev = self.OpenDevice(BoardAddress) + # print "Open OK " + str(self.dev) + except: + self.dev = _K8055_CLOSED + raise IOError, "Could not open device" + # print "Open error" + + def __str__(self): + """String format (almost) as from K8055 program""" + if self.__opentest() == True: # Device open + all = self.ReadAllValues() + return str(all[1])+";"+str(all[2])+";"+str(all[3])+";"+str(all[4])+";"+str(all[5]) + else: + return "" + + def __opentest(self): + if self.dev == _K8055_CLOSED: + return False + else: + return True + + def OpenDevice(self,BoardAddress): + """Open the connection to K8055 + + k=k8055() + try; + k.OpenDevice(0) # possible (address 0/1/2/3) + except IOError: + ... + returns 0 if OK, + Throws IOError if invalid board or not accessible + """ + if self.__opentest() == False: # Not open yet + self.dev = _pyk8055.OpenDevice(BoardAddress) + if self.dev == K8055_ERROR: + raise IOError, "Could not open device" + # print "Open OK " + str(self.dev) + return self.dev + + def CloseDevice(self): + """Close the connection to K8055 + + k.CloseDevice() + + retuns 0 if OK else -1 + """ + if self.dev != _K8055_CLOSED: + ret = _pyk8055.CloseDevice() + self.dev = _K8055_CLOSED + return ret + + def OutputAnalogChannel(self,Channel,value=0): + """Set analog output channel value, default 0 (0-255)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.OutputAnalogChannel(Channel,value) + + def ReadAnalogChannel(self,Channel): + """Read data from analog input channel (1/2)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.ReadAnalogChannel(Channel) + + def ReadAllAnalog(self): + """Read data from both analog input channels at once + + Returns list, [return-value,channel_data1, channel_data2] + + """ + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.ReadAllAnalog() + + def OutputAllAnalog(self,data1,data2): + """Set both analog output channels at once (0-255,0-255)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.OutputAllAnalog(data1,data2) + + def ClearAllAnalog(self): + """Set all (both) analog output channels to 0 (low)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.ClearAllAnalog() + + def ClearAnalogChannel(self,Channel): + """Set analog output channel (1/2)to 0 (low)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.ClearAnalogChannel(Channel) + + def SetAnalogChannel(self,Channel): + """Set analog output channel (1/2) to 0xFF (high)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.SetAnalogChannel(Channel) + + def SetAllAnalog(self): + """Set all (both) analog output channels to 0xFF (high)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.SetAllAnalog() + + def WriteAllDigital(self,data): + """Write digital output channel bitmask (0-255)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.WriteAllDigital(data) + + def ClearDigitalChannel(self,Channel): + """Clear digital output channel (1-8)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.ClearDigitalChannel(Channel) + + def ClearAllDigital(self): + """Set all digital output channels low (0)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.ClearAllDigital() + + def SetDigitalChannel(self,Channel): + """Set digital output channel (1-8)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.SetDigitalChannel(Channel) + + def SetAllDigital(self): + """Set all digital output channels high (1)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.SetAllDigital() + + def ReadDigitalChannel(self,Channel): + """Read digital input channel (1-5), returns 0/1 (-1 on error)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.ReadDigitalChannel(Channel) + + def ReadAllDigital(self): + """Read all digital input channels - bitmask + + returns mask 0x00 - 0x1f, 0x01 as channel 1, 0x02 as channel 2... + retuns -1 on error + + """ + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.ReadAllDigital() + + def ResetCounter(self,CounterNo): + """Reset input counter (1/2), input channel 1/2""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.ResetCounter(CounterNo) + + def ReadCounter(self,CounterNo): + """Read input counter (1/2), input channel 1/2""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.ReadCounter(CounterNo) + + def SetCounterDebounceTime(self,CounterNo, DebounceTime): + """Set counter debounce time on counter 1/2 (1-7450 ms)""" + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.SetCounterDebounceTime(CounterNo,DebounceTime) + + # Makes no sense to switch to another class here + def SetCurrentDevice(self): + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.SetCurrentDevice(self.Address) + + # This function makes no sense in this context as + # the device is already open + #def SearchDevices(self): + #return _pyk8055.SearchDevices() + + def DeviceAddress(self): + return self.Address + + def IsOpen(self): + return self.__opentest() + + def ReadAllValues(self): + """Read data from all input channels at once + + Returns list, [return-value,digital input data, analog channel_data1, analog channel_data2, counter1, counter2] + + """ + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.ReadAllValues() + def SetAllValues(self,digitaldata, addata1, addata2): + if self.__opentest() == False : return K8055_ERROR + return _pyk8055.SetAllValues(digitaldata, addata1, addata2) + + def Version(self): + return _pyk8055.Version(); + + def DebugOn(self): + _pyk8055.cvar.DEBUG = 1 + def DebugOff(self): + _pyk8055.cvar.DEBUG = 0 + + def RawInput(self): + return _pyk8055.RawInput() + def DumpInput(self): + return "In <-"+_pyk8055.DumpInput() + def DumpOutput(self): + return "Out->"+_pyk8055.DumpOutput() + +%} +extern int OpenDevice (long int BoardAddress); +extern int CloseDevice (void); +extern long int ReadAnalogChannel (long int Channelno); +extern int ReadAllAnalog (long int *data1, long int *data2); +extern int OutputAnalogChannel (long int Channel, long int data); +extern int OutputAllAnalog (long int data1, long int data2); +extern int ClearAllAnalog (void); +extern int ClearAnalogChannel (long int Channel); +extern int SetAnalogChannel (long int Channel); +extern int SetAllAnalog (void); +extern int WriteAllDigital (long int data); +extern int ClearDigitalChannel (long int Channel); +extern int ClearAllDigital (void); +extern int SetDigitalChannel (long int Channel); +extern int SetAllDigital (void); +extern int ReadDigitalChannel (long int Channel); +extern long int ReadAllDigital (void); +extern int ResetCounter (long int counternr); +extern long int ReadCounter (long int CounterNo); +extern int SetCounterDebounceTime (long int CounterNo, long int DebounceTime); +extern int ReadAllValues (long int *data1, long int *data2, long int *data3, long int *data4, long int *data5); +extern int SetAllValues(int digitaldata, int addata1, int addata2); +extern long SetCurrentDevice(long deviceno); +extern long SearchDevices(void); +extern char *Version(void); diff --git a/pyk8055/pyplotA.py b/pyk8055/pyplotA.py new file mode 100755 index 0000000..6d19e29 --- /dev/null +++ b/pyk8055/pyplotA.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# $Id: pyplotA.py,v 1.2 2007/03/15 14:55:38 pjetur Exp $ +# +# Simple plotting of analog input data from the K8055 board +# +# based on the running plot sample from pyQwt +# The Python version of qwt-*/examples/data_plot/data_plot.cpp + +import random, sys +from qt import * +from qwt import * +from Numeric import * +from pyk8055 import * + + +class DataPlot(QwtPlot): + + def __init__(self, *args): + QwtPlot.__init__(self, *args) + + # Initialize data + self.x = arrayrange(0.0, 100.1, 0.5) + self.a1 = zeros(len(self.x), Float) + self.a2 = zeros(len(self.x), Float) + + self.setTitle("Simple K8055 datascope") + self.setAutoLegend(True) + + self.curve1 = self.insertCurve("Input 1") + self.curve2 = self.insertCurve("Input 2") + + self.setCurvePen(self.curve1, QPen(Qt.red)) + self.setCurvePen(self.curve2, QPen(Qt.blue)) + + # No automatic scaling, set y-scale 0-255 + self.setAxisScale(QwtPlot.yLeft,0,255,50) + + # set marker line in the middle - value 128 + mY = self.insertLineMarker("", QwtPlot.yLeft) + self.setMarkerYPos(mY, 128.0) + + self.setAxisTitle(QwtPlot.xBottom, "Time (seconds)") + self.setAxisTitle(QwtPlot.yLeft, "Values") + + self.startTimer(50) + + self.k = k8055(0) + # __init__() + + def timerEvent(self, e): + + # data moves from left to right: + # shift data array right and assign new value data[0] + + self.a1 = concatenate((self.a1[:1], self.a1[:-1]), 1) + self.a1[0] = self.k.ReadAnalogChannel(1) + + self.a2 = concatenate((self.a2[:1], self.a2[:-1]), 1) + self.a2[0] = self.k.ReadAnalogChannel(2) + + self.setCurveData(self.curve1, self.x, self.a1) + self.setCurveData(self.curve2, self.x, self.a2) + + self.replot() + + # timerEvent() + +# class DataPlot + +def main(args): + app = QApplication(args) + demo = make() + app.setMainWidget(demo) + app.exec_loop() + +# main() + +def make(): + demo = DataPlot() + demo.resize(500, 300) + demo.show() + return demo + +# make() + +# Admire +if __name__ == '__main__': + main(sys.argv) diff --git a/pyk8055/pyplotA_1.png b/pyk8055/pyplotA_1.png Binary files differnew file mode 100644 index 0000000..56ed71d --- /dev/null +++ b/pyk8055/pyplotA_1.png diff --git a/pyk8055/pyplotD.py b/pyk8055/pyplotD.py new file mode 100755 index 0000000..9145b37 --- /dev/null +++ b/pyk8055/pyplotD.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# $Id: pyplotD.py,v 1.2 2007/03/15 14:55:38 pjetur Exp $ +# +# Simple plotting of digital input data from the K8055 board +# +# based on the running plot sample from pyQwt +# The Python version of qwt-*/examples/data_plot/data_plot.cpp + +import random, sys +from qt import * +from qwt import * +from Numeric import * +from pyk8055 import * + +class DataPlot(QwtPlot): + + def __init__(self, *args): + QwtPlot.__init__(self, *args) + + # Initialize data + self.x = arrayrange(0.0, 100.1, 0.5) + self.d1 = 0.0 + zeros(len(self.x), Float) + self.d2 = 1.0 + zeros(len(self.x), Float) # shift data up 1 + self.d3 = 2.0 + zeros(len(self.x), Float) # Shift data up 2... + self.d4 = 3.0 + zeros(len(self.x), Float) + self.d5 = 4.0 + zeros(len(self.x), Float) + + self.setTitle("Simple K8055 datascope") + self.setAutoLegend(True) + + self.curve1 = self.insertCurve("Input 1") + self.curve2 = self.insertCurve("Input 2") + self.curve3 = self.insertCurve("Input 3") + self.curve4 = self.insertCurve("Input 4") + self.curve5 = self.insertCurve("Input 5") + + self.setCurvePen(self.curve1, QPen(Qt.red)) + self.setCurvePen(self.curve2, QPen(Qt.blue)) + self.setCurvePen(self.curve3, QPen(Qt.green)) + self.setCurvePen(self.curve4, QPen(Qt.black)) + self.setCurvePen(self.curve5, QPen(Qt.cyan)) + + # Make data plot shape square + self.setCurveStyle(self.curve1, QwtCurve.Steps) + self.setCurveStyle(self.curve2, QwtCurve.Steps) + self.setCurveStyle(self.curve3, QwtCurve.Steps) + self.setCurveStyle(self.curve4, QwtCurve.Steps) + self.setCurveStyle(self.curve5, QwtCurve.Steps) + + # Fixed axis here from 0 to 5 + self.setAxisScale(QwtPlot.yLeft,0,5,1) + + self.setAxisTitle(QwtPlot.xBottom, "Time (seconds)") + self.setAxisTitle(QwtPlot.yLeft, "Values") + + self.startTimer(50) + + # init the K8055 board + self.k = k8055(0) + # __init__() + + def timerEvent(self, e): + + # data moves from left to right: + # shift data array right and assign new value data[0] + + self.d1 = concatenate((self.d1[:1], self.d1[:-1]), 1) + self.d1[0] = self.k.ReadDigitalChannel(1) * 0.95 + + self.d2 = concatenate((self.d2[:1], self.d2[:-1]), 1) + self.d2[0] = self.k.ReadDigitalChannel(2) * 0.95 + 1 # Shift data up 1 + + self.d3 = concatenate((self.d3[:1], self.d3[:-1]), 1) + self.d3[0] = self.k.ReadDigitalChannel(3) * 0.95 + 2 # Shift data up 2... + + self.d4 = concatenate((self.d4[:1], self.d4[:-1]), 1) + self.d4[0] = self.k.ReadDigitalChannel(4) * 0.95 + 3 + + self.d5 = concatenate((self.d5[:1], self.d5[:-1]), 1) + self.d5[0] = self.k.ReadDigitalChannel(5) * 0.95 + 4 + + self.setCurveData(self.curve1, self.x, self.d1) + self.setCurveData(self.curve2, self.x, self.d2) + self.setCurveData(self.curve3, self.x, self.d3) + self.setCurveData(self.curve4, self.x, self.d4) + self.setCurveData(self.curve5, self.x, self.d5) + + self.replot() + + # timerEvent() + +# class DataPlot + +def main(args): + app = QApplication(args) + demo = make() + app.setMainWidget(demo) + app.exec_loop() + +# main() + +def make(): + demo = DataPlot() + demo.resize(500, 300) + demo.show() + return demo + +# make() + +# Admire +if __name__ == '__main__': + main(sys.argv) + diff --git a/pyk8055/pyplotD_2.png b/pyk8055/pyplotD_2.png Binary files differnew file mode 100644 index 0000000..1603cf4 --- /dev/null +++ b/pyk8055/pyplotD_2.png diff --git a/pyk8055/setup.py b/pyk8055/setup.py new file mode 100644 index 0000000..b1a1c85 --- /dev/null +++ b/pyk8055/setup.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +import os,sys,string +from distutils.core import setup, Extension + +__revision__ = "$Id: setup.py,v 1.3 2007/03/28 10:17:57 pjetur Exp $" + +if os.environ.has_key('VERSION'): + version=os.environ['VERSION'] +else: + from subprocess import * + try: + version = Popen(["grep ^VERSION ../Makefile | cut -d '=' -f 2 | tr -d '\n'"], stdout=PIPE, shell=True).communicate()[0] + except: + version='?.?' + +build_modules = [Extension('_pyk8055', + define_macros = [('VERSION', "\"%s\"" % str(version))], + libraries=["usb"], + sources=['libk8055.i',"../libk8055.c"])] + +setup( + name='pyk8055', + version=version, + author='Pjetur G. Hjaltason', + author_email='pjetur@pjetur.net', + description='K8055 library wrapper', + url='http://libk8055.sourceforge.net/', + ext_modules =build_modules, + py_modules=['pyk8055'] +) diff --git a/velleman.rules b/velleman.rules new file mode 100644 index 0000000..f1afc8f --- /dev/null +++ b/velleman.rules @@ -0,0 +1,19 @@ +# velleman.rules a udev rules file for velleman K8055/VM110. +# Put this file in /etc/udev/rules.d +# +# To access the devices under a regular user account, you must +# be in the k8055 group. +# +# You can add a RUN="..." attribute to run some arbitrary script +# when the device is plugged in. + +SUBSYSTEM !="usb_device", ACTION !="add", GOTO="velleman_rules_end" + +SYSFS{idVendor}=="10cf", SYSFS{idProduct}=="5500", SYMLINK+="k8055_0" +SYSFS{idVendor}=="10cf", SYSFS{idProduct}=="5501", SYMLINK+="k8055_1" +SYSFS{idVendor}=="10cf", SYSFS{idProduct}=="5502", SYMLINK+="k8055_2" +SYSFS{idVendor}=="10cf", SYSFS{idProduct}=="5503", SYMLINK+="k8055_3" + +MODE="0660", GROUP="k8055" + +LABEL="velleman_rules_end" |