From 9bfdbb1d569eea229fd9f10823891234c8676145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Zurcher?= Date: Fri, 18 Feb 2011 17:39:44 +0100 Subject: initial commit, version 0.4.1 from http://sourceforge.net/projects/libk8055 --- Makefile | 72 + README.txt | 37 + java/build.xml | 213 +++ java/src/c/jk8055.c | 398 ++++++ java/src/java/net/sf/libk8055/jk8055/JK8055.java | 812 +++++++++++ .../net/sf/libk8055/jk8055/JK8055Exception.java | 73 + .../java/net/sf/libk8055/jk8055/JK8055Test.java | 400 ++++++ java/src/java/net/sf/libk8055/jk8055/overview.html | 7 + java/src/java/net/sf/libk8055/jk8055/package.html | 8 + k8055.h | 55 + libk8055.c | 600 +++++++++ main.c | 295 ++++ man/k8055.1.gz | Bin 0 -> 1843 bytes pyk8055/Makefile | 37 + pyk8055/frmk8055qt.ui | 1422 ++++++++++++++++++++ pyk8055/frmk8055qt.ui.h | 260 ++++ pyk8055/k8055.py | 117 ++ pyk8055/k8055qt.png | Bin 0 -> 33894 bytes pyk8055/k8055qt.py | 232 ++++ pyk8055/k8055test.py | 70 + pyk8055/k8055testm.py | 98 ++ pyk8055/libk8055.i | 352 +++++ pyk8055/pyplotA.py | 88 ++ pyk8055/pyplotA_1.png | Bin 0 -> 21901 bytes pyk8055/pyplotD.py | 113 ++ pyk8055/pyplotD_2.png | Bin 0 -> 20543 bytes pyk8055/setup.py | 31 + velleman.rules | 19 + 28 files changed, 5809 insertions(+) create mode 100644 Makefile create mode 100644 README.txt create mode 100644 java/build.xml create mode 100644 java/src/c/jk8055.c create mode 100644 java/src/java/net/sf/libk8055/jk8055/JK8055.java create mode 100644 java/src/java/net/sf/libk8055/jk8055/JK8055Exception.java create mode 100644 java/src/java/net/sf/libk8055/jk8055/JK8055Test.java create mode 100644 java/src/java/net/sf/libk8055/jk8055/overview.html create mode 100644 java/src/java/net/sf/libk8055/jk8055/package.html create mode 100644 k8055.h create mode 100644 libk8055.c create mode 100644 main.c create mode 100644 man/k8055.1.gz create mode 100644 pyk8055/Makefile create mode 100644 pyk8055/frmk8055qt.ui create mode 100644 pyk8055/frmk8055qt.ui.h create mode 100755 pyk8055/k8055.py create mode 100644 pyk8055/k8055qt.png create mode 100644 pyk8055/k8055qt.py create mode 100755 pyk8055/k8055test.py create mode 100644 pyk8055/k8055testm.py create mode 100644 pyk8055/libk8055.i create mode 100755 pyk8055/pyplotA.py create mode 100644 pyk8055/pyplotA_1.png create mode 100755 pyk8055/pyplotD.py create mode 100644 pyk8055/pyplotD_2.png create mode 100644 pyk8055/setup.py create mode 100644 velleman.rules 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 " 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 @@ + + + + + java wrapper for libk8055 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 +#ifdef USE_VELLEMAN_DLL + // assumes that Velleman DLL Version 2 has been installed + #define bool int + #include +#else + // assumes that the c library as been installed with header file + #include +#endif +#include +#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 http://libk8055.sourceforge.net/ + * @author Martin Pischky + * + */ +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. + *
+ * 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 + * 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 + * 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. + *
+ * 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 || 2Note + *
Once a specific device address is connected with a program + * another program can't get access to it. + * + * @return + *
 
+	 * 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.
+	 * 
+ * @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<= 0; i--) { + jk8055.WriteAllDigital( 1<=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< 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 @@ + + +

+This document is the API specification for JK8055 - A java wrapper for libk8055. +

+ + 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 @@ + + +

JK8055 - A java wrapper for libk8055.

+

The wrapper can be used on Linux with libk8055 (see +http://libk8055.sourceforge.net/) +or the standard Vellemann DLLs on Windows. + + diff --git a/k8055.h b/k8055.h new file mode 100644 index 0000000..4d5ae81 --- /dev/null +++ b/k8055.h @@ -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 +#include +#include +#include +#include +#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); +} diff --git a/main.c b/main.c new file mode 100644 index 0000000..a6fa602 --- /dev/null +++ b/main.c @@ -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 * + * Edward Nys * + * * + * 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 +#include +#include +#include +#include +#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; i3){ + 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 +K8055QT +Python:#from kdecore import * +Python:from kdeui import * +Python:from pyk8055 import * + + + + K8055QT + + + + 0 + 0 + 600 + 314 + + + + K8055 Status + + + + OutputGroup + + + + 320 + 70 + 270 + 51 + + + + Digital Output + + + + OutputBox5 + + + + 140 + 20 + 30 + 21 + + + + 5 + + + Digital Output 5 + + + + + OutputBox6 + + + + 169 + 20 + 30 + 21 + + + + 6 + + + Digital Output 6 + + + + + OutputBox7 + + + + 199 + 20 + 30 + 21 + + + + 7 + + + Digital Output 7 + + + + + OutputBox8 + + + + 229 + 20 + 30 + 21 + + + + 8 + + + Digital Output 8 + + + + + OutputBox1 + + + + 10 + 20 + 30 + 21 + + + + 1 + + + Digital Output 1 + + + + + OutputBox2 + + + + 42 + 20 + 30 + 21 + + + + 2 + + + Digital Output 2 + + + + + OutputBox3 + + + + 76 + 20 + 30 + 21 + + + + 3 + + + Digital Output 3 + + + + + OutputBox4 + + + + 110 + 20 + 30 + 21 + + + + 4 + + + Digital Output 4 + + + + + + InputGroup + + + + 320 + 130 + 270 + 70 + + + + Digital Input + + + + DigitaltextLabel1 + + + + 18 + 40 + 20 + 20 + + + + 1 + + + AlignCenter + + + + + DigitaltextLabel4 + + + + 170 + 40 + 20 + 20 + + + + 4 + + + AlignCenter + + + + + DigitaltextLabel5 + + + + 220 + 40 + 20 + 20 + + + + 5 + + + AlignCenter + + + + + DigitaltextLabel2 + + + + 69 + 40 + 20 + 20 + + + + 2 + + + AlignCenter + + + + + DigitaltextLabel3 + + + + 120 + 40 + 20 + 20 + + + + 3 + + + AlignCenter + + + + + DigitalLed1 + + + + 20 + 20 + 20 + 20 + + + + Off + + + + 255 + 0 + 0 + + + + Digital 1 input state + + + + + DigitalLed2 + + + + 70 + 20 + 20 + 20 + + + + Off + + + + 255 + 0 + 0 + + + + Digital 2 input state + + + + + DigitalLed3 + + + + 121 + 20 + 20 + 20 + + + + Off + + + + 255 + 0 + 0 + + + + Digital 3 input state + + + + + DigitalLed4 + + + + 173 + 20 + 20 + 20 + + + + Off + + + + 255 + 0 + 0 + + + + Digital 4 input state + + + + + DigitalLed5 + + + + 221 + 20 + 20 + 20 + + + + Off + + + + 255 + 0 + 0 + + + + Digital 5 input state + + + + + + groupCounter1 + + + + 320 + 200 + 271 + 51 + + + + Counter 1 + + + + + 1 ms + + + + + 2 ms + + + + + 5 ms + + + + + 10 ms + + + + + 50 ms + + + + + 100 ms + + + + + 500 ms + + + + + 1000 ms + + + + + 2000 ms + + + + comboCounter1 + + + + 171 + 20 + 90 + 21 + + + + Debounce value counter #1 + + + + + Counter1Value + + + + 20 + 20 + 71 + 21 + + + + Plain + + + Flat + + + Counter #1 + + + + + ClearCounter1 + + + + 100 + 20 + 60 + 21 + + + + Reset + + + Reset Counter #1 + + + + + + groupCounter2 + + + + 320 + 250 + 271 + 51 + + + + Counter 2 + + + + + 1 ms + + + + + 2 ms + + + + + 5 ms + + + + + 10 ms + + + + + 50 ms + + + + + 100 ms + + + + + 500 ms + + + + + 1000 ms + + + + + 2000 ms + + + + comboCounter2 + + + + 171 + 20 + 90 + 21 + + + + Debounce value counter #2 + + + + + Counter2Value + + + + 20 + 20 + 71 + 21 + + + + Plain + + + Flat + + + Counter #2 + + + + + ClearCounter2 + + + + 100 + 20 + 60 + 21 + + + + Reset + + + Reset Counter #2 + + + + + + groupDigitalButtonBox + + + + 200 + 10 + 110 + 90 + + + + Digital + + + + ClearAllDigitalButton + + + + 10 + 50 + 90 + 30 + + + + Clear All + + + Clear all digital outputs + + + + + SetAllDigitalButton + + + + 10 + 20 + 90 + 30 + + + + Set All + + + Set all digital outputs + + + + + + groupAnalogButtonBox + + + + 200 + 110 + 110 + 90 + + + + Analog + + + + ClearAllAnalogButton + + + + 10 + 50 + 90 + 30 + + + + Clear All + + + Set all analog outputs low + + + + + SetAllAnalogButton + + + + 10 + 20 + 90 + 30 + + + + Set All + + + Set all analog outputs high + + + + + + groupTestButtonBox + + + + 200 + 210 + 110 + 90 + + + + Test + + + + TestAnalogButton + + + + 10 + 50 + 90 + 30 + + + + Analog + + + Run analog tests + + + + + TestDigitalButton + + + + 10 + 20 + 90 + 30 + + + + Digital + + + Run digital output tests + + + + + + groupBoxAD2 + + + + 140 + 10 + 45 + 290 + + + + AD2 + + + + BarAD2 + + + + 16 + 20 + 20 + 230 + + + + 255 + + + 1 + + + Vertical + + + Analog input value - AD2 + + + + + AD2Value + + + + 10 + 260 + 30 + 20 + + + + NoFrame + + + 3 + + + Flat + + + Analog value AD2 + + + + + + groupBoxAD1 + + + + 100 + 10 + 45 + 290 + + + + AD1 + + + + AD1Value + + + + 10 + 260 + 30 + 20 + + + + NoFrame + + + 3 + + + Flat + + + Analog value AD1 + + + + + BarAD1 + + + + 15 + 20 + 20 + 230 + + + + 255 + + + 1 + + + Vertical + + + Analog input value - AD1 + + + + + + groupBoxDA2 + + + + 55 + 10 + 45 + 290 + + + + DA2 + + + + DA2Value + + + + 10 + 260 + 30 + 20 + + + + NoFrame + + + 3 + + + Flat + + + Analog value DA2 + + + + + BarDA2 + + + + 15 + 20 + 20 + 230 + + + + 255 + + + 1 + + + Vertical + + + Analog output value - DA2 + + + + + + groupBoxDA1 + + + + 10 + 10 + 45 + 290 + + + + DA1 + + + + DA1Value + + + + 10 + 260 + 30 + 20 + + + + NoFrame + + + 3 + + + Flat + + + Analog value DA1 + + + + + BarDA1 + + + + 15 + 20 + 20 + 230 + + + + 255 + + + 1 + + + Vertical + + + Analog output value - DA1 + + + + + + groupCard + + + + 320 + 10 + 271 + 51 + + + + Card + + + + CardRadioGroup + + + + 10 + 19 + 151 + 20 + + + + NoFrame + + + + + + + CardButton1 + + + + 0 + 0 + 30 + 21 + + + + 1 + + + true + + + Select Card #1 + + + + + CardButton3 + + + + 80 + 0 + 30 + 21 + + + + 3 + + + Select Card #3 + + + + + CardButton2 + + + + 40 + 0 + 30 + 21 + + + + 2 + + + Select Card #2 + + + + + CardButton4 + + + + 120 + 0 + 30 + 21 + + + + 4 + + + Select Card #4 + + + + + + ConnectButton + + + + 179 + 15 + 80 + 30 + + + + Connect + + + Connect to selected card + + + + + + + ConnectButton + clicked() + K8055QT + ConnectButton_clicked() + + + CardButton1 + clicked() + K8055QT + CardButton1_clicked() + + + CardButton2 + clicked() + K8055QT + CardButton2_clicked() + + + ClearCounter2 + clicked() + K8055QT + ClearCounter2_clicked() + + + OutputBox1 + clicked() + K8055QT + OutputBox1_clicked() + + + ClearCounter1 + clicked() + K8055QT + ClearCounter1_clicked() + + + OutputBox8 + clicked() + K8055QT + OutputBox8_clicked() + + + OutputBox7 + clicked() + K8055QT + OutputBox7_clicked() + + + OutputBox2 + clicked() + K8055QT + OutputBox2_clicked() + + + OutputBox3 + clicked() + K8055QT + OutputBox3_clicked() + + + OutputBox4 + clicked() + K8055QT + OutputBox4_clicked() + + + OutputBox5 + clicked() + K8055QT + OutputBox5_clicked() + + + OutputBox6 + clicked() + K8055QT + OutputBox6_clicked() + + + SetAllAnalogButton + clicked() + K8055QT + SetAllAnalogButton_clicked() + + + ClearAllAnalogButton + clicked() + K8055QT + ClearAllAnalogButton_clicked() + + + SetAllDigitalButton + clicked() + K8055QT + SetAllDigitalButton_clicked() + + + ClearAllDigitalButton + clicked() + K8055QT + ClearAllDigitalButton_clicked() + + + BarAD2 + valueChanged(int) + K8055QT + BarAD2_valueChanged(int) + + + BarAD1 + valueChanged(int) + K8055QT + BarAD1_valueChanged(int) + + + comboCounter2 + activated(int) + K8055QT + comboCounter2_activated(int) + + + comboCounter1 + activated(int) + K8055QT + comboCounter1_activated(int) + + + TestDigitalButton + clicked() + K8055QT + TestDigitalButton_clicked() + + + TestAnalogButton + clicked() + K8055QT + TestAnalogButton_clicked() + + + CardButton3 + clicked() + K8055QT + CardButton3_clicked() + + + CardButton4 + clicked() + K8055QT + CardButton4_clicked() + + + + frmk8055qt.ui.h + + + Kpriv; + Kp = False; + + + ConnectButton_clicked() + CardButton1_clicked() + CardButton2_clicked() + CardButton3_clicked() + CardButton4_clicked() + init() + ClearCounter1_clicked() + ClearCounter2_clicked() + OutputBox1_clicked() + OutputBox2_clicked() + OutputBox3_clicked() + OutputBox4_clicked() + OutputBox5_clicked() + OutputBox6_clicked() + OutputBox7_clicked() + OutputBox8_clicked() + SetAllAnalogButton_clicked() + ClearAllAnalogButton_clicked() + SetAllDigitalButton_clicked() + ClearAllDigitalButton_clicked() + BarAD1_valueChanged( int ) + BarAD2_valueChanged( int ) + comboCounter2_activated( int ) + comboCounter1_activated( int ) + TestDigitalButton_clicked() + TestAnalogButton_clicked() + + + + kled.h + kled.h + kled.h + kled.h + kled.h + + 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 new file mode 100644 index 0000000..85647db Binary files /dev/null and b/pyk8055/k8055qt.png differ 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)) + "
" + # read the counter on input 1 + res+= "Counter(1)=" + str(self.k.ReadCounter(1)) + "
" + # 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 new file mode 100644 index 0000000..56ed71d Binary files /dev/null and b/pyk8055/pyplotA_1.png differ 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 new file mode 100644 index 0000000..1603cf4 Binary files /dev/null and b/pyk8055/pyplotD_2.png differ 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" -- cgit v1.1-2-g2b99