Outp in Linux

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Joseph
  • Registratie: April 2008
  • Laatst online: 12-07 12:41
Waarschijnlijk is dit een kleinigheid, maar ik kan het (hier) iig niet vinden.

Ik ben bezig wat te experimenteren in C#. Ik heb er een handboek bij. Maar helaas lijkt die meer Windows, of zelfs DOS orienterend te zijn.

Mijn vraag is simpel. Het boek draagt een groot stuk code aan. Ik wist een heleboel errors te fixen naar een error. Hij begrijpt de statement outp(); namelijk niet. Het hele programma werkt, nadat ik de functie eruit had gesloopt. Het is namelijk een functie voor de PC speaker.

Het gaat om deze code.
C#: beep.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
beep()
{
    unsigned freq = 280, time = 300000;
    long t1, t2, ii;
    
    outp( 0x43, 0xb6 );
    outp( 0x42, freq );
    outp( 0x42, freq >> 8 );
    outp( 0x61, 0x4f );
    
    for( ii = 1; ii < time; ii++ );
        outp( 0x61, 0x4d );
        
}


Ik denk dat ik de Linux variant van outp() nodig heb. Maar ik had ergens gelezen dat deze statement uitgefaseerd was.

Heeft iemand de clue?

Acties:
  • 0 Henk 'm!

  • Styxxy
  • Registratie: Augustus 2009
  • Laatst online: 12-07 12:30
Dit is C/C++-code, geen C#. Het enige dat ik over outp() vond was dit:
http://www.daniweb.com/so...opment/cpp/threads/240245

Daarnaast, welke header files heb je ge-include, aangezien ik outp() niet bepaald vond bij mij.

[ Voor 16% gewijzigd door Styxxy op 31-05-2011 19:07 ]


Acties:
  • 0 Henk 'm!

  • Joseph
  • Registratie: April 2008
  • Laatst online: 12-07 12:41
Volgens mij is die functie uitgefaseerd. Ik denk dat ik gebruik moet maken van de Linux API's, om de hardware aan te spreken.

Alleen ik kan weinig vinden over API's van de Linux kernel. Waarschijnlijk gebruik ik te complexe zoektermen. Heeft iemand pointers? :)

Acties:
  • 0 Henk 'm!

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 14:19

Ventieldopje

I'm not your pal, mate!

Is dit misschien wat je zoekt?

http://linux.die.net/man/2/outb aangezien outp inderdaad uitgefaseerd is ;)

Voorbeeld code: http://www.faqs.org/docs/...-Port-Programming.html#s9

[ Voor 28% gewijzigd door Ventieldopje op 31-05-2011 19:31 ]

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


Acties:
  • 0 Henk 'm!

  • Joseph
  • Registratie: April 2008
  • Laatst online: 12-07 12:41
Die code kijk ik net naar. Hierbij moet je voor elk commando specifiek toegang geven tot een hardware adres.
Als ik nu dit wil doen:
C#: beep.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
beep()
{
    unsigned freq = 280, time = 300000;
    long t1, t2, ii;
    
        ioperm();
    outp( 0x43, 0xb6 );
    outp( 0x42, freq );
    outp( 0x42, freq >> 8 );
    outp( 0x61, 0x4f );
    
    for( ii = 1; ii < time; ii++ );
        outp( 0x61, 0x4d );
        
}

Hiermee gebruik ik ioperm om de onderstaande set opdracht te permitten. Alleen dat gaat niet. Heeft iemand een idee?

Acties:
  • 0 Henk 'm!

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 10:26

Reptile209

- gers -

Wel even de juiste parameters specificeren hè :). Zie een stuk hoger op dezelfde pagina:
[...]The syntax is ioperm(from, num, turn_on), where from is the first port number to give access to, and num the number of consecutive ports to give access to. For example, ioperm(0x300, 5, 1) would give access to ports 0x300 through 0x304 (a total of 5 ports). The last argument is a Boolean value specifying whether to give access to the program to the ports (true (1)) or to remove access (false (0)). You can call ioperm() multiple times to enable multiple non-consecutive ports. See the ioperm(2) manual page for details on the syntax. [...]

[ Voor 4% gewijzigd door Reptile209 op 31-05-2011 21:07 ]

Zo scherp als een voetbal!


Acties:
  • 0 Henk 'm!

  • yade
  • Registratie: Mei 2002
  • Laatst online: 02-06 11:10
Dit is absoluut geen C# code, en die for loop doet volgens mij ook niets dankzij die puntkomma.

Acties:
  • 0 Henk 'm!

  • jmzeeman
  • Registratie: April 2007
  • Laatst online: 10-07 22:43
Die for loop is een uiterst professionele (ahum) delay, zie ook freq en time. En inderdaad lijkt me dit geen c# maar C++.
Ik weet niet wat voor boek je hebt maar ik zou naar een ander boek opzoek gaan.

@yade:
Oh oeps iets te snel er van uigegaan dat dit dezelfde soort code was die ik recent nog tegen kwam voor een μc.

[ Voor 41% gewijzigd door jmzeeman op 03-06-2011 09:38 ]


Acties:
  • 0 Henk 'm!

  • yade
  • Registratie: Mei 2002
  • Laatst online: 02-06 11:10
Het inspringen suggereert dat er wat anders bedoeld wordt.

Acties:
  • 0 Henk 'm!

  • Gimmeabrake
  • Registratie: December 2008
  • Laatst online: 01:47
Ik heb de ballen verstand van C, maar het lijkt me verstandig om de puntkomma bij de for-loop weg te halen :p
C:
1
2
for( ii = 1; ii < time; ii++ ) //HIER STOND EEN ;
        outp( 0x61, 0x4d ); 


Daarnaast wil ik nog even benadrukken dat dit geen C# is maar C of C++. Aan een C# handboek heb je bij deze talen vrij weinig: ookal verschilt de naam nauwelijks en lijkt de syntax soms best veel op elkaar zitten er grote, fundamentele verschillen tussen die talen. Zoeken naar een C of C++ boek dus! ;)

edit: vreemd. Deze topic staat bij mij bovenaan in PRG, zie zojuist dat de laatste reactie 2 dagen geleden was. En mijn puntkomma opmerking is al een keer gemaakt door yade, zie het nu pas. Ach, het is nog vroeg :+

[ Voor 17% gewijzigd door Gimmeabrake op 03-06-2011 10:37 ]


Acties:
  • 0 Henk 'm!

  • leuk_he
  • Registratie: Augustus 2000
  • Laatst online: 11-07 14:23

leuk_he

1. Controleer de kabel!

Het inspringen is fout, de ; is "goed".


De for loop is er om een vertraging te genereren, het outp commando is er om de timer los te koppelen van de speaker, dus het geluid uit te zetten.

In dos had dit goed gewerkt, onder linux heb je als het goed is de hardware afgeschermd van gebruikers programma's. De loop werkt ook niet goed, op een snelle CPU zal deze te snel zijn, op een goede compiler wordt hij weggeoptimaliseerd.

dus het is onverstandig om in 2011 een pc op deze manier geluid te laten maken. (als je het over embedded hardware hebt is het aansturen van poorten wel een optie)

Need more data. We want your specs. Ik ben ook maar dom. anders: forum, ff reggen, ff topic maken
En als je een oplossing hebt gevonden laat het ook ujb ff in dit topic horen.


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 10-07 20:18
Zoals genoemd komt de code uit het real-mode DOS tijdperk waarin je je hardware nog direct aanstuurde (hoewel er niets DOS-specifieks aan de code is). Niettemin zijn de meeste PCs tegenwoordig nog wel redelijk compatible met de originele IBM PC, en zou je het geheel wel onder Linux werken moeten krijgen. Er zijn echter wel een aantal problemen met de code:
  1. Zoals leuk_he terecht opmerkt is een vertraging introduceren met een lusje not done, omdat de duur ervan onvoorspelbaar is. (Overigens optimaliseert GCC -- toch een goede compiler, mijns inziens -- dit soort lusjes juist expres niet weg.) De oplossing is simpel: gebruik gewoon sleep() of (onder Linux/POSIX) nanosleep() om een vertraging te introduceren.
  2. Onder een modern besturingssysteem kun je niet zomaar naar alle poorten schrijven; daar moet je eerst permissie voor vragen. ioperm() is daar inderdaad de geschikte functie voor, maar je moet natuurlijk wel de goede argumenten meegeven.
  3. Er is geen standaardfunctie voor outp() voor zover ik weet, aangezien dat een x86-specifieke instructie is, maar je kunt 'm wel zelf introduceren met behulp van een inline assembly statement.
  4. Tenslotte is de waarde die je naar port 42h schrijft géén frequentie, maar een vertraging. De PC speaker timer heeft een kloksnelheid van 1.193.180 Hz, dus om de juiste vertraging te berekenen moet je die frequentie delen door de frequentie van de gewenste toon.
Door dit alles te combineren, kom ik op zoiets uit:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <unistd.h>
#include <sys/io.h>

#define outp(port, value) \
    asm("outb %1, %0" : : "d"((short)(port)), "a"((char)(value)));

void beep(unsigned freq)
{
    unsigned delay = 1193180/freq;      /* convert frequency to delay */
    outp(0x43, 0xb6);                   /* initialize PC  speaker */
    outp(0x42, delay & 0xff);           /* write delay low byte */
    outp(0x42, delay >> 8);             /* write delay high byte */
    outp(0x61, 0x4f);                   /* enable output */
    sleep(1);                           /* wait 1 second */
    outp(0x61, 0x4d);                   /* disable output */
}

int main()
{
    if (ioperm(0x42, 2, 1) != 0 || ioperm(0x61, 1, 1) != 0)
    {
        perror("ioperm()");
        return 1;
    }
    beep(280 /* Hz */);
    return 0;
}

Ik vermoed dat dit zou moeten werken, maar ik heb het niet getest, aangezien ik mijn PC-speaker fysiek niet aangesloten heb. :P

edit:
D'oh! Er blijken ook gewoon een macro outb in sys/io.h gedefinieerd te worden. Die kun je dus beter gebruiken in plaats van een eigen macro.

[ Voor 4% gewijzigd door Soultaker op 03-06-2011 13:49 ]

Pagina: 1