Linux Parino-mini-HOWTO

v2.2, 11 september 2004
Bart Geverts <web(at)sys1(dot)ath(dot)cx>
Licentie: GFDL 1.2


Deze howto beschrijft hoe je de Parino onder Linux kan gebruiken.

Inhoud

1. Introductie
2. Algemene informatie
3. De uitgangen
4. De ingangen
5. Toegang
6. inb() en outb()
7. Software
8. Toepassingen
9. Links
10. Download

1. Introductie

Parino is een afkorting welke staat voor:

    PARallel
    ||| INput
    ||| || Output
    ||| || |
    ||| || |
    ------------+
    PAR-IN-O    =      PARINO

De PARINO (meer hierover) is een kaart waarmee de PC grip kan krijgen op zijn omgeving. Het geheel wordt op een printerpoort van de PC aangesloten en kan via twaalf relais en vijf ingangen respectievelijk actie ondernemen en waarnemingen doen.

De PARINO wordt geleverd met besturingssoftware welke alleen geschikt is voor DOS. Om de PARINO ook onder Linux te kunnen gebruiken heb ik een stukje software ontwikkeld en deze korte 'HOWTO' geschreven.

De PARINO kaart heeft 12 relaisuitgangen. Dat houdt in dat er 12 aparte schakelaars op zitten die ieder afzonderlijk aan of uit gezet kunnen worden. Ieder schakelaar is een relais dat er voor zorgt dat er geen verbinding bestaat tussen de spanning die geschakeld wordt en de spanning in de computer. Hierdoor wordt het inwendige van je PC beschermd.

Om verwarring te voorkomen heb ik in de Linux-software de namen van de uitgangen hetzelfde gelaten als de namen die onder DOS worden gebruikt. De uitgangen heten achtereenvolgens 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B en C.

De kaart heeft verder 5 ingangen. Een ingang is een aansluiting die door de computer kan worden ingelezen. Met ander woorden, het is een vorm van terugkoppeling naar de computer toe. Wanneer er een sensor op wordt aangesloten, kan de PC bijvoorbeeld weten of de temperatuur te hoog is of niet.
Ook de 5 ingangen zijn "galvanisch gescheiden" van de computer. Dat betekent dat er geen stromen lopen tussen sensor en computer. In de praktijk gebeurt dit door met zogenaamde optische koppelingen te werken. Zo'n optische koppeling bestaat uit een lampje en een lichtgevoelige cel. Wanneer het lampje uit is, dan meet de computer een andere waarde dan wanneer het lampje aan is. Hierdoor voorkomt een foute aansluiting aan een ingang, schade aan de computer zelf.

Om verwarring te voorkomen heb ik in de Linux-software de namen van de ingangen hetzelfde gelaten als de namen die onder DOS worden gebruikt. De ingangen heten achtereenvolgens P, Q, R, S en T.

2. Algemene informatie

BASE is het basisadres van de printerpoort. Dit basisadres is, afhankelijk van de configuratie 0x3bc, 0x378 of 0x278. Om de Parino te besturen worden drie poorten gebruikt:

  • BASE : Datapoort
  • BASE+1 : Statuspoort
  • BASE+2 : Controlpoort

BASE (Datapoort) is een Write-Only poort. Een lees-opdracht geeft de laatst geschreven waarde terug. Via deze poort worden de relais 2, 3, 4, 5, 6, 7, 8 en 9 aan en uit gezet.

BASE+1 (Statuspoort) is een Read-Only poort. Op deze poort wordt de status van de ingangen P, Q, R, S en T opgevraagd. Schrijven naar deze poort heeft geen effect.

BASE+2 (Controlpoort) is een Write-Only poort. Een lees-opdracht geeft de laatst geschreven waarde terug. Via deze poort worden de relais 1, A, B en C aan en uit gezet.

Om vanuit een userspace programma direct naar/van poorten te schrijven/lezen, moet je je programma hiervoor de rechten geven. Dat kan je doen met de ioperm() functie. Bij een kernelmodule is dat niet nodig.

Programma's die gebruik maken van de ioperm() functie kunnen in principe alleen door root worden uitgevoerd. Verderop in deze howto zal worden uitgelegd hoe ook andere users gebruik kunnen maken van deze programma's.

3. De uitgangen

Om de schakelaars 2 tot en met 9 aan of uit te zetten moet er een byte naar poort BASE worden geschreven volgens onderstaande tabel.

  +------------+--------------+--------------+
  | schakelaar |  byte (hex)  |  byte (bin)  |
  +------------+--------------+--------------+
  |     2      |     0x01     |   0000 0001  |
  |     3      |     0x02     |   0000 0010  |
  |     4      |     0x04     |   0000 0100  |
  |     5      |     0x08     |   0000 1000  |
  |     6      |     0x10     |   0001 0000  |
  |     7      |     0x20     |   0010 0000  |
  |     8      |     0x40     |   0100 0000  |
  |     9      |     0x80     |   1000 0000  |
  +------------+--------------+--------------+

Om meerdere schakelaars aan te zetten worden de bytes van de schakelaars geORed. B.v. om schakelaar 2 en 3 aan te zetten:

  bin:                              hex:
    0000 0001                         0x01
    0000 0010                         0x02
    --------- OR                      ---- OR
    0000 0011                         0x03

moet dus 0x03 naar poort BASE worden geschreven.

De logica achter de schakelaars 1, A, B en C is iets ingewikkelder, maar wordt in de volgende tabel verklaard. Ook alle mogelijke combinaties getoond.

  +------------+--------------+--------------+-------------------+
  | schakelaar | waarde (hex) | waarde (bin) | bit 0, 1 en 3 inv |
  +------------+--------------+--------------+-------------------+
  |   -        |     0x0b     |   0000 1011  |     0000 0000     |
  |   1        |     0x0a     |   0000 1010  |     0000 0001     |
  |   A        |     0x09     |   0000 1001  |     0000 0010     |
  |   1A       |     0x08     |   0000 1000  |     0000 0011     |
  |   B        |     0x0f     |   0000 1111  |     0000 0100     |
  |   1B       |     0x0e     |   0000 1110  |     0000 0101     |
  |   AB       |     0x0d     |   0000 1101  |     0000 0110     |
  |   1AB      |     0x0c     |   0000 1100  |     0000 0111     |
  |   C        |     0x03     |   0000 0011  |     0000 1000     |
  |   1C       |     0x02     |   0000 0010  |     0000 1001     |
  |   AC       |     0x01     |   0000 0001  |     0000 1010     |
  |   1AC      |     0x00     |   0000 0000  |     0000 1011     |
  |   BC       |     0x07     |   0000 0111  |     0000 1100     |
  |   1BC      |     0x06     |   0000 0110  |     0000 1101     |
  |   ABC      |     0x05     |   0000 0101  |     0000 1110     |
  |   1ABC     |     0x04     |   0000 0100  |     0000 1111     |
  +------------+--------------+--------------+-------------------+
  opm: De bits 4, 5, 6 en 7 staan hier voor de volledigheid, maar spelen geen
  rol.

In de laatste kolom zijn de bits 0, 1 en 3 geinverteerd. Dit is ooit door IBM bedacht, maar waarom is mij niet helemaal duidelijk. Als je hier meer over wil lezen, kijk dan eens in de IBM Parallel Port FAQ/Tutorial.

Om meerdere schakelaars aan te zetten worden de bytes, nadat de bits 0, 1 en 3 geinvereerd zijn, geORed. B.v. om schakelaar 1 en A aan te zetten:

  bin:                                       hex:
    0000 1010  --inv->  0000 0001              0x0a  --inv->  0x01
    0000 1001  --inv->  0000 0010              0x09  --inv->  0x02
                        --------- OR                          ---- OR
    0000 1000  <-inv--  0000 0011              0x08  <-inv--  0x03

moet dus 0x03 naar poort BASE+2 worden geschreven.

4. De ingangen

Om de ingangen P, Q, R, S en T op te vragen moet er een byte van poort BASE+1 worden gelezen. De ingelezen byte komt overeen met de ingangen zoals vermeld in onderstaande tabel.

  +------------+------------+-------------+--------+
  | byte (hex) | byte (bin) | bit 0-6 inv | ingang |
  +------------+------------+-------------+--------+
  |   0x3f     |  0011 1111 |  0100 0000  |   P    |
  |   0xff     |  1111 1111 |  1000 0000  |   Q    |
  |   0x5f     |  0101 1111 |  0010 0000  |   R    |
  |   0x6f     |  0110 1111 |  0001 0000  |   S    |
  |   0x7f     |  0111 0111 |  0000 1000  |   T    |
  +------------+------------+-------------+--------+

Hier moeten behalve bit 7, alle bits worden geinverteerd. Dit is ooit door IBM bedacht, maar waarom is mij niet helemaal duidelijk. Als je hier meer over wil lezen, kijk dan eens in de IBM Parallel Port FAQ/Tutorial.

5. Toegang

Om vanuit userspace een poort te bereiken, moet je je programma hier toegang toe geven. Dat kan met de functie ioperm(). De syntax van deze functie is: ioperm(<from>, <num>, <turn_on>). Ioperm zet de poort toegang bits van <num> poorten vanaf adres <from> op <turn_on>. Met ioperm() kan je alleen de eerste 0x3ff I/O poorten bereiken, maar dat maakt in dit geval niets uit omdat de hoogst mogelijke poort (0x378) daar nog onder valt. De ioperm() aanroep vereist van het programma dat het root-privilages heeft; je moet om het programma runnen dus als root zijn ingelogd of je moet met setuid aan de gang gaan. Meer informatie over ioperm() is te vinden in 'man ioperm'. In het hoofdstuk 'Webinterface' is meer te lezen over toegang voor non-root.

6. inb() en outb()

Om naar/van poorten te schrijven/lezen moet je gebruik maken van de functies inb() en outb(). Met inb(<port>) lees je een byte in van poort <port>. Met de functie outb(<value>, <port>) schrijf je een waarde <value> naar poort <port>*. *: Deze volgorde is net anderom dan onder DOS gebruikelijk is.

7. Software

In de loop der jaren heb ik meerdere stukjes software in elkaar gerommeld, variërend van buggy userspacetools tot iets dat serieus op een kernelmodule lijkt. Om hier serieus mee aan de gang te gaan adviseer ik om de recentste code te gebruiken, maar ter 'leering en vermaeck' zijn ook m'n oudere creaties hier te vinden.

De eerste versie is 'parinotools-1.0' gedoopt en bestaat uit drie eenvoudige commandline tooltjes om relais aan en uit te zetten en om de status uit te lezen. In de daaropvolgende 'parinotools-2.01' zijn deze tooltjes samengevoegd in één executable en is het geheel wat gestroomlijnder gemaakt. In de recentste versie is het compleet anders aangepakt. De 'parinodrv-2.6' bestaat uit een kernelmodule (Linux 2.6.x). Via /dev/parino zijn de relais te besturen in uit /proc/parino kan de status worden uitgelezen.

Onder aan deze pagina zijn de downloadlinkjes te vinden.

parinotools-1.0

set
Met het programma set is het mogelijk om vanaf de commandline een schakelaar op de PARINO te SETten. De naam van de schakelaar wordt als parameter meegegeven. B.v. met de opdracht 'set 8' wordt schakelaar 8 geSET. Andere schakelaars worden hierdoor niet beinvloed omdat het programma eerst op poort BASE en BASE+2 opvraagt welke schakelaars er zijn geSET. De waarde die bij schakelaar 8 hoort wordt hiermee geORed en het resultaat wordt naar BASE of BASE+2 geschreven. Op het moment dat ik deze howto schrijf is versie 1.0 de laatste versie van set. Deze versie heb ik een paar weken in de praktijk gebruikt en ik heb geen fouten kunnen ontdekken.

unset
Het programma unset is de tegenhanger van het programma set, en zorgt ervoor dat vanaf de commandline een schakelaar geUNSET kan worden. De syntax van unset is gelijk aan die van set en het beinvloed de ander schakelaars niet omdat de waarde van de gewenste schakelaar wordt geNOT en geAND met de huidige waarde op BASE of BASE+2. Omdat de omtwikkeling van dit programma synchoon loopt met set, is ook hiervan de laatste versie 1.0. Ook in deze unset v0.9 heb na een paar weken gebruiken geen foutjes kunnen ontdekken.

status
Om te controleren welke schakelaars er geSET zijn en op welke ingangen een spanning staat is het programma status geschreven. Het programma status wordt zonder parameters gestart waarna het op het scherm alle geSETte schakelaars weergeeft en de ingangen waarop een spanning staat. De laatste versie van status is versie 1.0 en ook dit programma lijkt nu goed te werken.

parinotools-2.1

In versie 2.1 zijn deze tools samengevoegd in 1 programma. Versie 2.0 bevatte wat bugjes, welke in versie 2.1 zijn gefixed. De syntax is als volgt:

  # parino

Het programma zonder parameters geeft de status van de Parino. Alle geSETte relais en ingangen waar spanning op staan worden als 1 string weergegeven.

  # parino <parameter>

Als er een parameter wordt opgegeven moet deze beginnen met een '+' of een '-'. Alle relais-namen achter de '+' worden geSET. De '-' zorgt ervoor dat alle opgegeven relais geUNSET worden. Enkele voorbeelden:

  # parino +18A

Zorgt ervoor dat de relais 1, 8 en A worden geSET. De syntax wijkt enigzins af van de syntax van de DOS software waarbij in 1 keer meerdere relais geSET en geUNSET kunnen worden. In deze Linux-versie is dat niet mogelijk.

In versie 2.01 wordt gebruik gemaakt van een configuratie bestand dat na installatie is te vinden in /etc/parino.conf. In dit bestand worden de volgende gegevens vastgelegd:

  • Basisadres van de printerpoort
  • Namen van de relais
  • Namen van de ingangen

parinodrv-2.6

Eenmalig de device node maken met "make node". Hoe en of dat met devfsd en udev werkt weet ik niet. Module compileren met "make". Module laden met "insmod ./parino.ko".

Relais 3, 4 en 8 AAN en 1, A en B UIT zetten:

  # echo "+348-1AB" > /dev/parino

Status uitlezen:

  cat /proc/parino

Basisadres van de printerpoort

Afhankelijk van de configuratie is dat 0x3bc, 0x378 of 0x278. Default staat deze op 0x3bc, omdat dat in mijn configuratie het adres van de printerpoort is. Maar in de meeste gevallen zal dat 0x378 zijn.

Namen van de relais en de ingangen

Default zijn deze namen gelijk aan de namen die onder DOS worden gebruikt. Voorlopig kunnen deze namen bestaan uit slechts 1 letter of cijfer. In toekomstige versies moet het mogelijk zijn om ook langere namen te kunnen gebruiken.

8. Toepassingen

Met behulp van de cron-deamon is het mogelijk om op gezette tijden bepaalde handelingen te verrichten. Als je b.v. elke ochtend om half acht verse koffie wilt, is dat met cron eenvoudige te automatiseren. Meer informatie hierover is te vinden in 'man cron', 'man 1 crontab' en 'man 5 crontab'.

Zelf ben ik eens creatief geweest met LEGO en heb ik een soort van lopende band gemaakt. Op die band lagen porties vissenvoer en een paar keer per dag kregen mijn twee goudvissen automatische te eten. Na ee tijdje waren die beesten zijn al zover dat als ze de band horen lopen, gelijk naar boven kwamen zwemmen. Intussen zijn ze allebei dood (ouderdom, niet door gebrek aan voer :) ).

9. Links

IBM Parallel Port FAQ/Tutorial
http://s.teoma.com/search?submit=Search&q=IBM+Parallel+Port+FAQ%2FTutorial

10. Download

parinotools-1.0.tar.gz: Deze versie is helaas ergens verloren gegaan. :-(

parinotools-2.1.tar.gz: Userspacetooltje om de parino te bedienen.

parinodrv-2.6.2.tar.gz: Parino kernelmodule die werkte tot linux-2.6.5.

parinodrv-2.6.8.tar.gz: Parino kernelmodule die werkt op linux-2.6.8 en latere kernels. Vermoedelijk ook op oudere 2.6 kernels.