| Menu (English) | | | Linux & Asm x86-32 | | | PIC microchip | | | Debian Packages | | | Links | | | Javastation Sun | | | Weblog | | | About |
| Menu (Nederlands) | | | Linux & Asm x86-32 | | | PIC microchip | | | Tux maakt koffie | | | Links | | | | | Weblog | | | Over |
|
|
Dit kan je natuurlijk op verschillende manieren doen. Het grootste probleem is natuurlijk dat het niet altijd evident is om kabels van de PC naar de koffiemachine (of eenders welk ander elektrisch toestel) te trekken. Daarom ben ik op zoek gegaan naar een draadloze manier om dit te verwezelijken. PHILIPS verkoopt draadloze afstands-schakelsystemen. Deze bestaan uit een draadloze zender die een of meedere apparaten kan bedienen. Hiervoor wordt gebruik gemaakt van een draadloze ontvanger die in het stopkontakt wordt gestoken. |
|
|
Deze afstandsbediening is vrij eenvoudig aan te passen, zodat je hem kan aansluiten op de PC. Het enige wat je daarvoor nodig hebt is een ULN2803. Ikzelf heb die afstandsbediening zo aangesloten op een IO-kaartje dat in mijn PC aanwezig is, maar het zou ook via de printerpoort moeten werken. |
|
||
|---|---|---|
Om uiteindelijk de afstandsbediening aan te sturen dien je de gepaste waarde naar de IO-poort (of printerpoort) te sturen. Onder GNU/Linux kan je dit bv. doen met hetvolgende C-programma, dat ik vroeger eens als voorbeeld heb ontvangen (LINUX.B fidonet).
= Deze bewaar ik : Linux ===============================================KeepIt=
Msg : 30 [1-87] Rcv
From : Pros Robaer 27-May-97 20:22:14 2:292/8013.4
To : Jan Wagemakers 2:292/8133
Subj : Linux & Assembler
=====================================================================REM_LINUX=
* Copied from: LINUX.B
Hallo Jan,
Op Sun, 25 May 97 08:29:28 +0200 schreef je naar Pros Robaer:
PR>> BTW: als je (zoals elke rechtgeaarde bitneuker) met je parallelle
PR>> poort of iets dergelijks wil gaan prossen, vergeet dan niet om eerst
PR>> netjes toestemming te vragen [ioperm()], of je programma vliegt er
PR>> uit...
JW> Whue, dat is voorlopig nog chinees voor mij ;-)
Net zo min als je geheugen mag gebruiken, dat niet aan jouw
programma is toegewezen door het OS, mag je geen I/O-poorten
gebruiken, zonder het eerst te vragen. Doe je het toch, dan werpt
het OS je programma er uit vanwege een "Segmentation Fault"...
Daarmee ben je nog niet klaar. Als "normale" user zal je geen
toestemming krijgen om zo'n programma uit te voeren. Remedie: ofwel
log je in als root, ofwel zet je het UID-bit v/h prog. Zo:
chown root.root poorttest
chmod 4755 poorttest
JW> En nu we er toch over bezig zijn, ik heb in mijn kompjoeter een zelfgebouwd
JW> (elektuur) I/O-kaartje zitten. Onder dos kan ik dan BV. Ledjes laten
JW> oplichten door : - mov dx,0310h
JW> - out dx,al
JW> Enig idee of dit ook onder Linux gaat?
Dit zou moeten werken:
----BEGIN-C-SOURCE---poorttest--------------------------------------
/*
* poorttest
*
* schrijf iets naar poort 0x310
*/
#include <stdio.h>
#include <stdlib.h>
#define INLINE inline
#include <unistd.h>
unsigned short poort = 0x310;
int byte;
static INLINE void
outb (short port, char val)
{
__asm__ volatile ("out%B0 %0,%1"::"a" (val), "d" (port));
}
/*
* voor het geval je een poort wil lezen.
* gebruik: byte = inb (het-adres-van-de-poort);
*/
static INLINE unsigned char
inb (short port)
{
unsigned int ret;
__asm__ volatile ("in%B0 %1,%0":"=a" (ret):"d" (port));
return ret;
}
int
main (int argc, char *argv[])
{
if (argc != 2)
{
printf (" Gebruik: %s <x>, waarbij x = 0...255\n", argv[0]);
exit (2);
}
/*
* als het programma meerdere malen naar dezelfde I/O-poort moet
* schrijven, volstaat het 1 maal ioperm () aan te roepen.
*/
ioperm (poort, 1, 1);
byte = atoi (&argv[1][0]);
outb (poort, byte);
}
----eind-C-SOURCE---------------------------------------------------
Plaats dit stuk potjeslatijn in een bestand (poorttest.c), en
compileer het met de magische woorden:
gcc -s -O3 -Wall -w -o poorttest poorttest.o
Hierna zou een "./poorttest 123" de byte 123 naar I/O-adres 0x310
moeten schrijven. Meer info vindt je in 1 v/d mini-HOWTO's.
Vriendelijke groeten vanwege
Pros (die ook al eens graag een bitje neukt :)
--- Sprot 1.0 #0001
* Origin: Rivendel (2:292/8013.4)
=====================================================================REM_LINUX=
Omdat ik echter iemand ben die een voorliefde heeft voor assembler, heb ik dit C-Programma omgezet naar assembler (GNU as). Niet dat dit echte voordelen heeft, de koffie zal niet merkbaar sneller klaar zijn ;-)
Hieronder zie je de assembler versie.
===============================================================================
.globl main
.type main,@function
main:
popl %ecx # Hoeveel argumenten?
cmpl $0x2, %ecx # port nummer --> Steeds 2 argumenten nodig
jne help # niet 2 --> geef help tekst
popl %ecx # skip argument 1 (= bestandsnaam prog)
movl $101, %eax # "ioperm" (system call = 101).
movl $0x310, %ebx
movl $1, %ecx
movl $0x310, %edx
int $0x80 # Vraag ioperm voor poort 0x310
popl %ecx # haal argument van stack : %ecx = nummer
call atoi # konverteer string (nummer) naar byte (%dl)
movl %edx, %eax # %al = nummer
movw $0x310, %dx # port 310(hex)
outb %al, %dx
jmp stop
help:
movl $gebruik, %ecx
movl $9, %edx
call print
movl (%esp), %ecx # ecx = argument 1 = naam programma
movl $1, %edx
lus:
cmpb $0, (%ecx)
je ok
incl %edx
incl %ecx
jmp lus
ok:
popl %ecx
call print
movl $info, %ecx
movl $26, %edx
call print
stop:
movl $1, %eax # Exit
movl $0, %ebx
int $0x80
#------------------------------------------------------------------------------
print: # Druk een string af
#------------------------------------------------------------------------------
# Ontvangt : %ecx = adres van de af te drukken string
# %edx = lengte van de af te drukken string
#------------------------------------------------------------------------------
movl $4, %eax # nummer van syscall 'write()'
movl $1, %ebx # schrijf naar stdout
int $0x80 # roep syscall aan
ret
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
atoi: # konverteer een string (0 ... 255) naar een getal.
#------------------------------------------------------------------------------
# Ontvangt : %ecx = adres van de te konverteren string
# Geef terug : %dl = het getal
#------------------------------------------------------------------------------
xorl %eax, %eax
xorl %ebx, %ebx
movl %ecx, %edi
incl %edi
cmpb $0, (%edi)
je l1
incl %edi
cmpb $0, (%edi)
je l2
l3:
movb (%ecx), %dl
subb $48, %dl
movb $100, %al
mulb %dl
movl %eax, %ebx
incl %ecx
l2:
movb (%ecx), %dl
subb $48, %dl
movb $10, %al
mulb %dl
incl %ecx
l1:
movb (%ecx), %dl
subb $48, %dl
addb %al, %dl
addb %bl, %dl
ret
#------------------------------------------------------------------------------
.data
gebruik:
.ascii "Gebruik: "
info:
.ascii " <x>, waarbij x = 0...255\n"
===============================================================================
as port.s -o port.o ld port.o -e main -o port
Zo, dit was het dan. Nu ga ik rustig een taske koffie drinken ;-)
Meer informatie over het maken van koffie met je PC vind je op http://www.tldp.org/HOWTO/mini/Coffee.html