Velleman K8000 & Linux HOWTO <author> <name> Heimo Schön <htmlurl url="mailto:Heimo Schön<heimo.schoen@gmx.at>" name="Heimo Schön <heimo.schoen@gmx.at>"> </author> <date>Version 0.4 , 6. Feb. 2002 <abstract> Setup a <htmlurl url="http://www.velleman.be/kits/k8000.htm" name="Velleman K8000"> on a <htmlurl url="http://www.linux.org" name="Linux"> System </abstract> </titlepag> <sect>Overview <sect1>About this HOWTO <p> This document describes how to setup your <htmlurl url="http://www.velleman.be/kits/k8000.htm" name="Velleman K8000 Board"> on a <htmlurl url="http://www.linux.org" name="Linux"> system, using the i2c Kerneldrivers <p> If you have any suggestions to this document, than feel free to contact me: <p> <itemize> <item>Heimo Schön <htmlurl url="mailto:heimo.schoen@gmx.at" name="<heimo.schoen@gmx.at>"> <item><htmlurl url="http://schoen.priv.at" name="http://schoen.priv.at"> </itemize> <p> Have a lot of fun with your Velleman K8000 Board. <p> <sect1>Links <p> Links to other sites with aditional information to K8000 running with Linux: <itemize> <item> <htmlurl url="http://yahoogroups.com/group/k8000" name="http://yahoogroups.com/group/k8000"> <item> <htmlurl url="http://struyve.mine.nu:8080/pageloader.pl?block=k8000" name="http://struyve.mine.nu:8080/pageloader.pl?block=k8000"> <item> <htmlurl url=""http://groups.yahoo.com/group/k8000/files/linux/libk8000/ name="http://groups.yahoo.com/group/k8000/files/linux/libk8000/"> </itemize> <p> <sect1>Thanks to <p> <itemize> <item><htmlurl url="mailto:hihihi <hihihi@wanadoo.nl>" name="hihihi <hihihi@wanadoo.nl>"> for his help in testing and correcting this mini-howto. </itemize> <p> <sect1>Version History <p> <itemize> <item> 0.1 08 Dec 2001 first trial <item> 0.2 28 Jan 2002 included a hint from Hihihi from NL to rmmod the lp-driver in the startscript <item> 0.3 3 Feb 2002 A lot of corrections and new features from <htmlurl url="mailto:hihihi <hihihi@wanadoo.nl>" name="hihihi <hihihi@wanadoo.nl>"> included <item> 0.4 6 Feb 2002 Minor bug fix from <htmlurl url="mailto:hihihi <hihihi@wanadoo.nl>" name="hihihi <hihihi@wanadoo.nl>"> </itemize> <p> <sect>Introduction <p> In this chapter I want to discribe the history of this mini-mini-howto. <sect1>Target <p> In 1995 I was searching for an expansion board for my home-PC. It was a PC-AT with 386 CPU and at that time I was programming with clipper. I wanted to read some digital and analog input and I thought that I don't want a board in my PC. I was searching for an external solutions. <p> I found the velleman K8000 board in an electronic shop. There was a source code for the driver available. I compiled this code with borland-C compiler and linked it together with my Clipper application. This program is running since Summer 1995 an doing some watching of my oil-heating at home. <p> Today this old machine is the last DOS-based machine at home. All other PCs are running with Linux. I searched through the web a lot of hours and found only the i2c-velleman.c Kernel-driver in the kernel-tree. But I couldn't find any examples, how to connect from a small C-program to the K8000 board. So I decided, to try to hack it by myself. After the program(s) was(were) running I wrote this small HOWTO. <p> However, if you find I could help you learning howto connect from C to your Velleman K8000 board, feel free to send me a short message. I would be happy to hear from you - I am sure thare there are some other K8000 user out there :-)) <p> In a discussion with <htmlurl url="mailto:hihihi <hihihi@wanadoo.nl>" name="hihihi <hihihi@wanadoo.nl>"> I found out that there also exists a velleman-library called libk8000. This HOWTO does not support this library-solution. Here I discribe the connection via kernel-drivers. At this point I want to thank <htmlurl url="mailto:hihihi <hihihi@wanadoo.nl>" name="hihihi <hihihi@wanadoo.nl>"> for his hints and for testing this HOWTO. <sect1>HW-Configuration <p> When you finished soldering your K8000, you should switch the two DIP-Switches to the off position. <sect1>SW-Configuration <p> You should prepare your system by running the following script (I stored it under the name "velle") <tscreen><verb> #! /bin/bash echo free the Parport ... /sbin/rmmod lp /sbin/rmmod parport_pc /sbin/rmmod vmppuser /sbin/rmmod parport echo i2c Treiber laden ... /sbin/modprobe i2c-velleman /sbin/modprobe i2c-dev echo create the device-handle and free it for all users cd /dev rm velleman # The following part was written by hihihi#wanadoo.nl # Jan 31 2002 # A variation on the ./velle script of Heimo Schoen. Filename=/proc/bus/i2c line="not empty yet" echo echo " Look for I2C devices in /proc/bus/i2c :" echo while [ "$line" != "" ] do read line echo " " $line if echo "$line" | grep -q "Velleman K8000" then K8000Entry=$line fi done <"$Filename" echo echo " Found a Velleman K8000 entry:" $K8000Entry echo K8000Nod=${K8000Entry#i2c-} echo $K8000Nod K8000Nod=`expr match "$K8000Nod" '\([0-9]*[0-9]\)'` echo $K8000Nod mknod velleman c 89 $K8000Nod chmod a+rw velleman echo Etwas auf die K8000 jagen ... echo hallo > /dev/velleman </verb></tscreen> You can download this script <htmlurl url="velleman.tgz" name="here"> <sect>the programs <sect1>check-i2c.c <p> This small C-program checks all addresses from 0 to 127 if there are reacheable i2c-chips connected to your parallel port. Before you start this program, you should compile and link it by typing make all and load all i2c kernel modules with the above described script named "velle" <tscreen><verb> /* ** $Id: check-i2c.c,v 0.01 ** ** File: check-i2c.c ** Author: Heimo Schoen / heimo.schoen@gmx.at ** ** Abstract: Routine for testing the Kerneldriver ** ../driver/char/i2cv-elleman.c ** # # Copyright (C) 2001,2002 by Heimo Schön <heimo.schoen@gmx.at> # # 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, BUT NOT (!!!) # 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., 675 Mass Ave, Cambridge, MA 02139, USA. # */ # include <errno.h> # include <stdio.h> # include <signal.h> # include <stdarg.h> # include <time.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <linux/i2c.h> #include <linux/i2c-dev.h> #include <unistd.h> int main(int argc, char *argv[]) { int fh = 0; unsigned int port = 0; int res; char devicename[100] = "/dev/velleman"; if (argc == 2) sprintf(devicename, "%s", argv[1]); fh = open(devicename, O_RDWR); if (fh < 3) { printf("\n"); printf("check-i2c had a problem opening %s\n", devicename); printf("\n"); printf(" please execute script velle included in the package check-i2c\n"); printf("\n"); printf(" You should have a file /dev/velleman generated with the command\n"); printf(" mknod /dev/velleman c 89 0\n"); printf("\n"); printf(" You also should have loaded i2c-velleman i2c-dev i2c-core and i2c-algo-bit\n"); printf(" into your kernel. See script velle for details how to do this\n"); printf("\n"); printf("usage of check-i2c:\n"); printf("\n"); printf(" check-i2c [devicename]\n"); printf("\n"); printf(" if parameter devicename is not given, check-i2c will try to open\n"); printf(" /dev/velleman.\n"); printf("\n"); printf("(c) 2001,2002 by Heimo Schön / heimo.schoen@gmx.at / http://schoen.priv.at\n"); printf("\n"); printf(" have a lot fun ...\n"); printf("\n"); exit (1); } else { printf("\n"); printf("check-i2c will search now on %s for reachable i2c-devices and will show you the addresses:\n", devicename); printf("\n"); // Loop across all available 7-Bit addresses for (port=0; port<=127; port++) { // Try to ioctl this device-address if (ioctl(fh, I2C_SLAVE, port) < 0) perror ("IOCTL Problem"); /* Using SMBus commands */ res = i2c_smbus_write_byte(fh, 0x00); if (res >= 0) printf("found i2c-chip at i2c-address: 0x%02x (%d) (real-address: 0x%02x)\n", port, port, port*2); //usleep(1000); } // loop port=0-127 printf("\n"); printf("NOTE:\n"); printf("the i2c-drivers in the kernel use a 7-bit adress.\n"); printf("E.g. if you want to write to a PCF8574A at the adress 0x70\n"); printf("than you have to divide 0x70 by two. This is 0x38, which is the\n"); printf("address for the kernel-drivers.\n"); printf("With other words, the kernel-driver is shifting your adress (0x38)\n"); printf("one byte left an adds 0 if you write ore 1 if you read from the\n"); printf("address.\n"); printf("I know, this is a little bit complecated ;-) But this is also the\n"); printf("reason why I wrote this small program\n"); printf("\n"); printf(" have a lot of fun ...\n"); printf("\n"); exit (0); } } </verb></tscreen> You can download this program with the Makefile <htmlurl url="velleman.tgz" name="here"> <sect1>velleman.c <p> velleman.c is doing some test with digital-output on your velleman K8000. This program is expecting that you have a K8000 connected to your /dev/lp0 and that all i2c drivers are loaded as described before. It switches all outputs on and off. There is a small help available (just read the source ;-) <tscreen><verb> /* ** $Id: velleman.c,v 0.01 ** ** File: velleman.c ** Author: Heimo Schoen / heimo.schoen@gmx.at ** ** Abstract: Routine for testing the Kerneldriver ** ../driver/char/i2cv-elleman.c ** # # Copyright (C) 2001,2002 by Heimo Schön <heimo.schoen@gmx.at> # # 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. # */ # include <errno.h> # include <stdio.h> # include <signal.h> # include <stdarg.h> # include <time.h> # include <sys/types.h> # include <sys/time.h> # include <sys/socket.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <linux/i2c.h> #include <linux/i2c-dev.h> #include <unistd.h> // ---------------------------------------------------------- int p_i2c_write(unsigned int vf_fh, unsigned int vf_port, unsigned char vf_data) { int vp_res; if (ioctl(vf_fh,I2C_SLAVE,vf_port)) perror ("IOCTL Problem"); vp_res = i2c_smbus_write_byte(vf_fh, ~vf_data); if (vp_res < 0) perror("i2c_smbus_write_byte"); return (vp_res); } // ---------------------------------------------------------- int p_write(unsigned int vf_fh, unsigned int vf_port, unsigned char vf_data) { int vp_res; unsigned char vp_buf[10]; if (ioctl(vf_fh,I2C_SLAVE,vf_port)) perror ("IOCTL Problem"); vp_buf[0] = ~vf_data; vp_res = write(vf_fh, vp_buf, 1); return (vp_res); } // ---------------------------------------------------------- int main(int argc, char *argv[]) { int fh = 0; int res; int i; unsigned int port1 = 0x38; unsigned int port2 = 0x39; unsigned char buf[10]; char devicename[100] = "/dev/velleman"; unsigned char testmode = 0; if (argc >= 2) { if (strlen(argv[1]) > 1) sprintf(devicename, "%s", argv[1]); if (strlen(argv[1]) == 1) testmode = atoi(argv[1]); } if (argc >= 3) { if (strlen(argv[2]) > 1) sprintf(devicename, "%s", argv[2]); if (strlen(argv[2]) == 1) testmode = atoi(argv[2]); } fh = open(devicename, O_RDWR); if (fh < 3) { printf("\n"); printf("velleman had a problem opening %s\n", devicename); printf("\n"); printf(" please execute script velle included in the package velleman\n"); printf("\n"); printf(" You should have a file /dev/velleman generated with the command\n"); printf(" mknod /dev/velleman c 89 0\n"); printf("\n"); printf(" You also should have loaded i2c-velleman i2c-dev i2c-core and i2c-algo-bit\n"); printf(" into your kernel. See script velle for details how to do this\n"); printf("\n"); printf("usage of velleman:\n"); printf("\n"); printf(" velleman [devicename] [test]\n"); printf("\n"); printf(" if parameter devicename is not given, velleman will try to open\n"); printf(" /dev/velleman.\n"); printf("\n"); printf(" parameter [test] has to be numeric and tells which testnumber you want\n"); printf(" If Parameter [test] is not found, velleman will only check the PCF8574A if present\n"); printf("\n"); printf("example: velleman /dev/i2c-0 2\n"); printf("\n"); printf("(c) 2001,2002 by Heimo Schön / heimo.schoen@gmx.at / http://schoen.priv.at\n"); printf("\n"); printf(" have a lot fun ...\n"); printf("\n"); exit (1); } else { // checking if we can find the two PCF5874A if (ioctl(fh,I2C_SLAVE,port1) < 0) perror ("IOCTL Problem"); res = i2c_smbus_write_byte(fh, 0x00); if (res >= 0) printf("found i2c-chip at i2c-address: 0x%02x (%d) (real-address: 0x%02x)\n", port1, port1, port1*2); if (ioctl(fh,I2C_SLAVE,port2) < 0) perror ("IOCTL Problem"); res = i2c_smbus_write_byte(fh, 0x00); if (res >= 0) printf("found i2c-chip at i2c-address: 0x%02x (%d) (real-address: 0x%02x)\n", port2, port2, port2*2); sleep(1); if (testmode == 1) { printf("Starting testmode 1 : Counter (stop test with CTRL-C)\n"); while (1) { /* Using SMBus commands */ for (i=0; i<=0xff; i++) { p_i2c_write(fh, port1, i); p_i2c_write(fh, port2, i); usleep(5); } } } if (testmode == 2) { printf("Starting testmode 2 : Knightrider (stop test with CTRL-C)\n"); while (1) { for (i=1; i<=15; i++) { if (i<=7) { p_write(fh, port1, 1<<i); p_write(fh, port2, 0); } else { p_write(fh, port2, 1<<(i-8)); p_write(fh, port1, 0); } usleep(1); } for (i=14; i>=0; i--) { if (i<=7) { p_write(fh, port1, 1<<i); p_write(fh, port2, 0); } else { p_write(fh, port2, 1<<(i-8)); p_write(fh, port1, 0); } usleep(1); } } } /* ioctl(fh,I2C_UDELAY,5); */ /* ioctl(fh,I2C_MDELAY, 2); */ /* ioctl(fh,I2C_RETRIES,3); */ if (ioctl(fh,I2C_SLAVE,port1) /* ioctl(fh, I2C_SLAVE, port1) */ < 0) perror ("IOCTL Problem"); errno = 0; res = ~ i2c_smbus_read_byte(fh); if (errno != 0) perror("i2c_smbus_read_byte"); else printf("i2c_smbus_read_byte: 0x%02x\n", res); sleep(1); /* Using I2C Read, equivalent of i2c_smbus_read_byte(file) */ res = read(fh,buf,1); if ( res == 1) printf("POSIX-Read: %d bytes buf[0]=0x%02x\n", res, ~ buf[0]); } return 0; } </verb></tscreen> You can download this program with the Makefile <htmlurl url="velleman.tgz" name="here"> <sect1>Makefile <p> Last but not least, the Makefile to the above two sources <tscreen><verb> # # Makefile for the velleman testprogram # # Copyright (C) 2001,2002 Heimo Schön <heimo.schoen@telecom.at> # # 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. # CFLAGS = -pedantic -Wall -O -g LDOPTIONS = -g -DYY_SKIP_YYWRAP RM = rm -f CP = cp -v STRIP = strip --verbose VELLEMANSRCS = velleman.c VELLEMANOBJS = $(patsubst %.c,%.o,$(VELLEMANSRCS)) CHECKSRCS = check-i2c.c CHECKOBJS = $(patsubst %.c,%.o,$(CHECKSRCS)) all:: velleman check-i2c tags: etags *.[hc] velleman: $(VELLEMANOBJS) $(DEPLIBS) $(RM) $@ $(CC) -o $@ $(VELLEMANOBJS) $(LDOPTIONS) -O0 -g -L/usr/lib/termcap -lreadline -lhistory -ltermcap check-i2c: $(CHECKOBJS) $(DEPLIBS) $(RM) $@ $(CC) -o $@ $(CHECKOBJS) $(LDOPTIONS) -O0 -g -L/usr/lib/termcap -lreadline -lhistory -ltermcap clean:: $(RM) velleman check-i2c *.o *~ depend:: @if [ -n "$(VELLEMANSRCS)" ] ; then set -x;\ $(DEPEND) $(DEPENDFLAGS) $(VELLEMANSRCS);\ fi @if [ -n "$(CHECKSRCS)" ] ; then set -x;\ $(DEPEND) $(DEPENDFLAGS) $(CHECKSRCS);\ fi </verb></tscreen> <sect1>notes <p> If you dont want to use the kernel-drivers, you find a solution for a user-space program <htmlurl url="http://struyve.mine.nu:8080/pageloader.pl?block=k8000" name="here"> <sect>Allgemeines <sect1>Copyright <p> Dieses Dokument ist urheberrechtlich geschützt. Das Copyright liegt bei Heimo Schön. <p> Das Dokument darf gemäß der GNU General Public License verbreitet werden. Insbesondere bedeutet dieses, daß der Text sowohl über elektronische wie auch physikalische Medien ohne die Zahlung von Lizenzgebühren verbreitet werden darf, solange dieser Copyright Hinweis nicht entfernt wird. Eine kommerzielle Verbreitung ist erlaubt und ausdrücklich erwünscht. Bei einer Publikation in Papierform ist der Autor zu informieren. <p> This howto is free documentation; 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, BUT NO later version. <p> This document 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. <p> You should have received a copy of the GNU General Public License along with this document; if not, write to the: Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. <p> </article> <!-- Keep this comment at the end of the file Local variables: mode: sgml sgml-omittag:t sgml-shorttag:t sgml-minimize-attributes:nil sgml-always-quote-attributes:t sgml-indent-step:1 sgml-indent-data:t sgml-parent-document:nil sgml-exposed-tags:nil sgml-local-catalogs:("/usr/lib/sgml-tools/dtd/catalog") sgml-local-ecat-files:nil End: -->