Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[EL] HD44780 LCD op de seriele poort aansluiten

Pagina: 1
Acties:
  • 131 views sinds 30-01-2008
  • Reageer

  • Steephh
  • Registratie: Juni 2003
  • Laatst online: 14:23
Omdat er nog niet veel te vinden was op GOT over het aansluiten van de HD44780 op de seriele poort is heb ik dit topic maar geopend.

Ik ben zelf bezig met een PII met linux om te bouwen naar een server. Nu wilde ik een 16x2 HD44780 compatible lcd schermpje aansluiten op die server. Nu was ik vergeten dat ik op de parallele poort al mijn printer wil aansluiten. Nu kan ik natuurlijk een extra isa/pci kaartje erin zetten, maar ik wil die sleuf nog overhouden voor een andere kaart (er zijn maar 3 pci sleuven vrij). Dus ik ben maar op internet gaan zoeken naar manieren om een HD44780 (die je volgens mij op de parallele poort moet aansluiten) aan te sluiten via de seriele aansluiting (of misschien zelfs via de smbus???). Nu ben ik deze site tegengekomen:

http://www.linuxfocus.org.../May2002/article236.shtml

Als ik het goed begrijp kan dus op die manier mijn lcd op de seriele poort aansluiten? Misschien ook een idee om deze link in de faq te zetten, het is wel een mooi projectje.

_@/'


  • Freek
  • Registratie: December 2001
  • Laatst online: 09-11 13:22
Op serieële zoeken ipv seriele scheelt al erg veel ;)

Volgens mij ondersteund bijna alle LCD software zowel de parallele als de serieële poort dus dit lijkt me geen probleem. Zeker niet omdat je ook nog eens een HD44780 chipset hebt wat geloof ik zo'n beetje de standaard is in casemod LCD land, dus ook schema's genoeg :)

  • Steephh
  • Registratie: Juni 2003
  • Laatst online: 14:23
Dus dan krijg je zoiets als dit:

Zelfbouw LCD backplate?

Maar kan ik de computer dan ook nog gegevens laten sturen?

Nou heb ik ook nog iets gevonden van een oude inkoopactie. Een controller waarmee je een lpt-lcd schermpje op de serieele poort kan aansluiten:

http://www.inkoopacties.net/ia/46t092qk/1

En op de site van de maker van die ic's staat ook een datasheet:

http://www.elabinc.com/ede700.pdf

Eigenijk heb ik gewoon hetzelfde probleem als deze persoon:

http://www.circuitsonline.net/forum/view/9433

Maar de site die in de TS staat, moet daar nu een serieel lcd op worden aangesloten, of een parallel? Want dan kan ik net zo goed dat gaan bouwen.

Op de parallele poort aansluiten is niet zo moeilijk. Daarvoor kan je heel makkelijk hier een aansluitschema vinden: http://www.crystalfontzlcd.tk/ Maar ik kan een serieel schema nergens vinden. Dit lijkt me ook wel logisch, aangezien serieel en parallel heel anders inmekaar zit.

[ Voor 18% gewijzigd door Steephh op 03-03-2005 11:00 ]

_@/'


  • Freek
  • Registratie: December 2001
  • Laatst online: 09-11 13:22
want de meeste logica zit in het Perl script en kan eenvoudig worden aangepast. Het paneel wordt via de seriële lijn op de computer aangesloten.
Eerste pagina van de site :o

  • Steephh
  • Registratie: Juni 2003
  • Laatst online: 14:23
Maar ik vind een stukje later:
1 x 2-lijns, 20 karakter LCD display met een HD44780 compatible interface.

Alle LCD's met 14 of 16 pennen aan de connector die ik ooit heb gezien waren compatibel met de HD44780. Je zou ook gebruik kunnen maken van 3- of 4- regelige display, maar dan moet de software een beetje worden aangepast.
Dus ik denk dat je het lcd gewoon zou moeten kunnen aansluiten, klopt dat?

En als naar dit schema kijk, zijn er gewoon maar 4 datalijnen aangesloten. Kan dat ook niet gewoon bij een parallel lcdtje?

Als ik me niet vergis, heb ik straks een lcdtje als deze:

http://www.crystalfontz.c...-color/CFAH1602BTMCJP.pdf

Ik moet hem nog krijgen, heb ik besteld via een inkoopactie.

[ Voor 14% gewijzigd door Steephh op 03-03-2005 11:15 ]

_@/'


  • Freek
  • Registratie: December 2001
  • Laatst online: 09-11 13:22
Ik denk het wel ja, let wel dat je hem niet zoals bij een parallele aansluiting gewoon zo kunt solderen maar dat er dus een MAX232 ic'tje tussen moet. Maargoed dat staat duidelijk in je schema :)

  • Cassettebandje
  • Registratie: Juli 2002
  • Laatst online: 21-11 20:56

Cassettebandje

SA-C90 TDK

je kunt ook gewoon schuifregistertjes op je seriele poort aansluiten als je dat wilt en daar dan het LCD aan. Dan hoef je niet moeilijk te doen met een microcontroller.

Als je dat wilt roep maar, dan maak ik een schematje voor je. Programmeren (of een bestaand programmatje ombouwen) moet je dan wel zelf doen.

  • Steephh
  • Registratie: Juni 2003
  • Laatst online: 14:23
Cassettebandje schreef op donderdag 03 maart 2005 @ 14:38:
je kunt ook gewoon schuifregistertjes op je seriele poort aansluiten als je dat wilt en daar dan het LCD aan. Dan hoef je niet moeilijk te doen met een microcontroller.

Als je dat wilt roep maar, dan maak ik een schematje voor je. Programmeren (of een bestaand programmatje ombouwen) moet je dan wel zelf doen.
Dat zou misschien wel fijn zijn. Zelf een programma maken of aanpassen was ik toch al van plan, dus dat is niet zo een probleem. Misschien is het toch handig om te weten welk lcd ik dan heb. Ff de correcte datasheet zoeken.

Dees dus: http://www.vtronic.com/image/pdf/lcmVt162a.pdf

Er staat bij dat de de kleuren yellow-green zijn, maar die zijn blue-white.

[ Voor 19% gewijzigd door Steephh op 03-03-2005 20:16 ]

_@/'


  • Cassettebandje
  • Registratie: Juli 2002
  • Laatst online: 21-11 20:56

Cassettebandje

SA-C90 TDK

Oké, hierbij het schema enzo:
Afbeeldingslocatie: http://atlas.et.tudelft.nl/mdhoop49/tweakers/hd44780-serieel.gif
Onderdelen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
C1      100n condensator
D1      4v7 zenerdiode
D2      4v7 zenerdiode
D3      4v7 zenerdiode
IC1     74LS164N (of iets anders dat met 
        74 begint en op 164 eindigt, zoals 74hct164)
JP1     LCD
R1      100 Ohm trimpotmeter
R2      10k Ohm trimpotmeter
R3      10k Ohm weerstand
R4      10k Ohm weerstand
R5      10k Ohm weerstand
X1      9 pins female subd connector
Hoe stuur je het aan:
- Klok eerst de databits in (D7 eerst): eerst RTS laag, D7 op DTR, RTS hoog maken en RTS weer laag maken. Dit tot en met D0
- Zet de waarde van RS op DTR
- Maak enable hoog en weer laag.

Schema (Eagle 4.13 light): http://atlas.et.tudelft.nl/mdhoop49/tweakers/main.sch

[ Voor 7% gewijzigd door Cassettebandje op 04-03-2005 19:34 ]


  • Steephh
  • Registratie: Juni 2003
  • Laatst online: 14:23
Ik kwam dit tegen op internet:
https://ssl.bulix.org/projects/lcd4linux/wiki/LCDTerm

Dat lijkt wel erg veel op jouw schema... Hoef ik dan geen programma te schrijven/aanpassen?

[ Voor 143% gewijzigd door Steephh op 15-03-2005 13:34 ]

_@/'


  • Cassettebandje
  • Registratie: Juli 2002
  • Laatst online: 21-11 20:56

Cassettebandje

SA-C90 TDK

Als je lcd4linux gebruikt dan hoef je niet zelf een programma te schrijven. Het projectje gebruikt echter een pic microcontroller en die moet je dan wel programmeren, het programmatje staat op die site ergens, je moet wel zelf een programmer bouwen.

Kies wat je wilt, het hangt er vanaf of je meer programmeer ervaring hebt of meer electronica ervaring wat de makkelijkste oplossing is.

  • Buzz-01
  • Registratie: Juni 2002
  • Laatst online: 21-11 14:40
Fake schreef op donderdag 03 maart 2005 @ 10:13:
Op serieële zoeken ipv seriele scheelt al erg veel ;)

Volgens mij ondersteund bijna alle LCD software zowel de parallele als de serieële poort dus dit lijkt me geen probleem. Zeker niet omdat je ook nog eens een HD44780 chipset hebt wat geloof ik zo'n beetje de standaard is in casemod LCD land, dus ook schema's genoeg :)
[mierenneukmodus] serle poort [/mierenneukmodus]
Verder: Hmm... ik ben met een soortgelijk projectje bezig, om het tezamen met wat fancontroller-code in een microcontroller te stompen.. Erg ver ben ik er alleen nog niet mee...

Flickr


  • miniK0bo
  • Registratie: December 2001
  • Laatst online: 11-05-2024
@ Hopeloosje, volgens mij begrijp BMRS je verhaal niet ....

  • Steephh
  • Registratie: Juni 2003
  • Laatst online: 14:23
miniK0bo schreef op dinsdag 15 maart 2005 @ 23:31:
@ Hopeloosje, volgens mij begrijp BMRS je verhaal niet ....
Ja, ik snap het eigenlijk ook niet. M'n lcd heb ik nog niet binnen, dus ik kan nog niet beginnen met bouwen. En ik ben nog bezig om een print te maken waarbij ik de banen aan één kant heb. Maar als ik een programma aanpas, hoef ik dan alleen maar die databits in te klokken, waarde van RS op DTR
en enable hoog en weer laag te zetten? En dan kan ik daarna gewoon het lcdtje op de gewone manier aansturen?

Programmeren ben ik beter in, dan met electronica te werken. PIC's heb ik nog nooit geprogrammeerd, en dan zou ik eerst zo'n PIC programmer moeten maken. Dus ik ga iig. voor jouw schema. Ik vind het trouwens ook geen probleem om eerst C of zo te leren, of iig een gedeelte daarvan.

Verder vroeg ik me af, of ik misschien eerst met dit programma de lcd handmatig ga aansturen, voordat ik andere programma's zoals lcdproc of lcd4linux ga aanpassen. Dan kan ik eventueel later ook nog altijd een programma zelf schrijven.

[ Voor 37% gewijzigd door Steephh op 16-03-2005 08:52 ]

_@/'


Verwijderd

Hopeloosje's schema is leuk, maar dat gaat redelijk cpu intensief zijn om het werkend te krijgen, bovendien moet je er zelf software voor schrijven om het te laten werken. Wellicht dat het met een, jaja, PIC16F628 wat mooier werkt. Je kunt eenvoudig in PICBASIC data uit de serieele poort halen en dit op het scherm weergeven, zodat je gewoon met hyperterminal (of minicom @ linux) data naar de seriele poort kunt gooien.

Voor code voorbeelden om de hd44780 aan te sturen met een PIC, kun je hier eens kijken.

[ Voor 23% gewijzigd door Verwijderd op 16-03-2005 14:31 ]


  • Steephh
  • Registratie: Juni 2003
  • Laatst online: 14:23
Verwijderd schreef op woensdag 16 maart 2005 @ 14:27:
Hopeloosje's schema is leuk, maar dat gaat redelijk cpu intensief zijn om het werkend te krijgen, bovendien moet je er zelf software voor schrijven om het te laten werken. Wellicht dat het met een, jaja, PIC16F628 wat mooier werkt. Je kunt eenvoudig in PICBASIC data uit de serieele poort halen en dit op het scherm weergeven, zodat je gewoon met hyperterminal (of minicom @ linux) data naar de seriele poort kunt gooien.

Voor code voorbeelden om de hd44780 aan te sturen met een PIC, kun je hier eens kijken.
Alle links op google doen het niet... En wat bedoel je met cpuintensief? Ik heb zelf een PII 350 MHz met 384 mb ram. Zal ik dat merken?

_@/'


  • Steephh
  • Registratie: Juni 2003
  • Laatst online: 14:23
Ik weet niet zeker of ik hier zomaar code mag posten, maar ik denk dat ik in een van deze 2 bestanden iets moet worden aangepast. Enne zie ^^, zal ik dat merken op m'n pc?

code:
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/*
 * Serial LPT driver module for Hitachi HD44780 based LCD displays by
 * Andrew McMeikan. The LCD is operated in it's 4 bit-mode through a
 * 4094 shift register and supports a keypad.
 *
 * Copyright (c)  1999 Andrew McMeikan <andrewm@engineer.com>
 *      modular driver 1999 Benjamin Tse <blt@Comports.com>
 *
 *              2001 Joris Robijn <joris@robijn.net>
 *                - Keypad support
 *                - Changed for 2 line wire control
 *
 * Full connection details at http://members.xoom.com/andrewmuck/LCD.htm
 *
 * printer port   4094/LCD
 * D2 (4)     EN  (6 - LCD)
 * D3 (5)     D   (2 - 4094)
 * D4 (6)     CLK (3 - 4094)
 * +Vcc       OE, STR (15, 1 - 4094)
 * D7 (9)     EN2 (6 - LCD2) (optional)
 *
 * 4094       LCD
 * Q1 (4)     D4 (11)
 * Q2 (5)     D5 (12)
 * Q3 (6)     D6 (13)
 * Q4 (7)     D7 (14)
 * Q6 (13)    RS (4)
 * Gnd            nRW (5)
 *
 * Keypad connection (optional):
 * This is connected on the 4094 parallel to the LCD.
 * Some diodes and resistors are needed, see further documentation.
 * Q1 (4)     Y0
 * Q2 (5)     Y1
 * Q3 (6)     Y2
 * Q4 (7)     Y3
 * Q5 (14)    Y4
 * Q6 (13)    Y5
 * Q7 (12)    Y6
 * The 'output' of the keys should be connected to the following LPT pins:
 * nACK   (10)    X0
 * BUSY   (11)    X1
 * PAPEREND (12)  X2
 * SELIN  (13)    X3
 * nFAULT (15)    X4
 * If you want to use as few LPT lines as possible, only use X0.
 *
 * This file is released under the GNU General Public License. Refer to the
 * COPYING file distributed with this package.
 */

#include "hd44780-serialLpt.h"
#include "hd44780.h"
#include "lpt-port.h"

#include "port.h"
#include "shared/str.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>

// Hardware specific functions
void lcdserLpt_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch);
void lcdserLpt_HD44780_backlight (unsigned char state);

unsigned char lcdserLpt_HD44780_scankeypad ();
void rawshift (unsigned char r);
void shiftreg (unsigned char displayID, unsigned char r);

#define RS       32
#define LCDDATA   8
#define LCDCLOCK 16
#define EN1       4
#define EN2      32

static unsigned int lptPort;
static char backlight_bit = 0;

// Initialisation
int
hd_init_serialLpt (HD44780_functions * hd44780_functions, lcd_logical_driver * driver, char *args, unsigned int port)
{
    unsigned char enableLines = EN1 | EN2;

    // Reserve the port registers
    lptPort = port;
    port_access(lptPort);
    port_access(lptPort+1);
    port_access(lptPort+2);

    hd44780_functions->senddata = lcdserLpt_HD44780_senddata;
    hd44780_functions->backlight = lcdserLpt_HD44780_backlight;
    hd44780_functions->scankeypad = lcdserLpt_HD44780_scankeypad;

    // setup the lcd in 4 bit mode
    shiftreg (enableLines, 3);
    hd44780_functions->uPause (15000);

    shiftreg (enableLines, 3);
    hd44780_functions->uPause (5000);

    shiftreg (enableLines, 3);
    hd44780_functions->uPause (100);

    shiftreg (enableLines, 3);
    hd44780_functions->uPause (100);

    shiftreg (enableLines, 2);
    hd44780_functions->uPause (100);

    hd44780_functions->senddata (0, RS_INSTR, FUNCSET | IF_4BIT | TWOLINE | SMALLCHAR);
    hd44780_functions->uPause (40);

    common_init ();

    return 0;
}

void
lcdserLpt_HD44780_senddata (unsigned char displayID, unsigned char flags, unsigned char ch)
{
    unsigned char enableLines;
    unsigned char portControl = 0;
    unsigned char h = ch >> 4, l = ch & 15;

    if (displayID == 1)
        enableLines = EN1;
    else if (displayID == 2)
        enableLines = EN2;
    else
        enableLines = EN1 | EN2;

    if (flags == RS_DATA)
        portControl = RS;
    else
        portControl = 0;

    shiftreg (enableLines, portControl | h);
    shiftreg (enableLines, portControl | l);

    // Restore line status for backlight
    port_out (lptPort, backlight_bit );
}

void
lcdserLpt_HD44780_backlight (unsigned char state)
{
    // Store new state
    backlight_bit = (state?LCDDATA:0);

    // Set line status for backlight
    port_out (lptPort, backlight_bit );
}

unsigned char lcdserLpt_HD44780_scankeypad ()
{
    // Unfortunately just bit shifting does not work with the 2-wire version...

    unsigned char keybits;
    unsigned int shiftcount;
    unsigned int shiftingbit;
    unsigned char readval, inputs_zero;
    int i;
    unsigned int scancode = 0;

    // While scanning the keypad, the 2-wire version executes the 0xFF
    // command. This command sets the cursor position, so it's harmless.
    // I could not prevent this, while staying compatible with both
    // wiring versions.

    // Clear the shiftregister, needed for 3-wire version
    rawshift(0);
    hd44780_functions->uPause (2);

    readval = ~ port_in (lptPort + 1) ^ INMASK;
    inputs_zero =  (((readval & FAULT) / FAULT <<4) |       /* pin 15 */
            ((readval & SELIN) / SELIN <<3) |       /* pin 13 */
            ((readval & PAPEREND) / PAPEREND <<2) |     /* pin 12 */
            ((readval & BUSY) / BUSY <<1) |         /* pin 11 */
            ((readval & ACK) / ACK ));          /* pin 10 */

    if( inputs_zero == 0 ) {
        // No keys were pressed

        // Restore line status for backlight.
        port_out (lptPort, backlight_bit );
        return 0;
    }

    // Scan the keypad while sending the first half of the command (high nibble)
    for (i = 7; i >= 0; i--) {              /* MSB first  */
        port_out (lptPort, LCDDATA);            /*set up data */
        port_out (lptPort, LCDDATA | LCDCLOCK);     /*rising edge of clock */

        hd44780_functions->uPause (2);

        if( !scancode ) {
            // Read input line(s)
            readval = ~ port_in (lptPort + 1) ^ INMASK;
            keybits = (((readval & FAULT) / FAULT <<4) |        /* pin 15 */
                ((readval & SELIN) / SELIN <<3) |       /* pin 13 */
                ((readval & PAPEREND) / PAPEREND <<2) |     /* pin 12 */
                ((readval & BUSY) / BUSY <<1) |         /* pin 11 */
                ((readval & ACK) / ACK ));          /* pin 10 */

            if( keybits != inputs_zero ) {
                shiftingbit = 1;
                for (shiftcount=0; shiftcount<KEYPAD_MAXX && !scancode; shiftcount++) {
                    if ( (keybits ^ inputs_zero ) & shiftingbit) {
                        // Found !
                        scancode = ((8-i)<<4) | (shiftcount+1);
                    }
                    shiftingbit <<= 1;
                }
            }
        }
    }

    // Wait for 2-wire version to clear the latch...
    hd44780_functions->uPause (6);

    // And again for the second half of the command (low nibble).
    // Needed for 2-wire version.
    rawshift (0xFF);

    // Wait for 2-wire version to clear the latch...
    hd44780_functions->uPause (6);

    // Restore line status for backlight.
    port_out (lptPort, backlight_bit );

    return scancode;
}

/* this function sends r out onto the shift register */
void
rawshift (unsigned char r)
{
    int i;

    for (i = 7; i >= 0; i--) {                      /* MSB first      */
        port_out (lptPort, ((r >> i) & 1) * LCDDATA);           /*set up data   */
        port_out (lptPort, (((r >> i) & 1) * LCDDATA) | LCDCLOCK);  /*rising edge of clock   */
    }
}

// enableLines = value on parallel port to toggle the correct display
void
shiftreg (unsigned char enableLines, unsigned char r)
{
    rawshift (r | 0x80);            // highest bit always set to 1 for Clear for 2-wire version
    port_out (lptPort, enableLines);    // latch it, to correct display
    hd44780_functions->uPause (1);
    port_out (lptPort, 0);          // for 3-wire version
    hd44780_functions->uPause (5);      // wait for 2-wire version to clear the latch...
}


Of in dit bestand?

code:
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/* $id$
 * Low level I/O functions taken from led-stat.txt
 * Jan 22 95 copyright damianf@wpi.edu
 *
 * DOS part (tested only with DOS version of GCC, DJGPP)
 * by M.Prinke <m.prinke@trashcan.mcnet.de> 3/97
 *
 * FreeBSD support by Guillaume Filion and Philip Pokorny, copyright 05/2001
 *
 * NetBSD & OpenBSD port by Guillaume Filion, copyright 12/2001
 *
 * (Better) FreeBSD port by Guillaume Filion, copyright 05/2002
 *
 * Improved support for old Linux (glibc1 and libc5) by Guillaume Filion, 12/2002
 */

/*
This file defines 4 static inline functions for port I/O:

// Read a byte from port
static inline int port_in (unsigned short int port);
// Returns the content of the byte.

// Write a char(byte) 'val' to port.
static inline void port_out (unsigned short int port, unsigned char val);
// Returns nothing.

// Get access to a specific port
static inline int port_access (unsigned short int port);
// Returns 0 if successful, -1 if failed

// Get access 3 to ports: port (CONTROL), port+1 (STATUS) and port+2 (DATA)
static inline int port_access_full (unsigned short int port);
// Returns 0 if successful, -1 if failed
*/

#ifndef PORT_H
#define PORT_H

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdio.h>

// -------------------------------------------------------------
// Use ioperm, inb and outb in <sys/io.h> (Linux)
#if defined HAVE_IOPERM

/* Glibc2 and Glibc1 */
# ifdef HAVE_SYS_IO_H 
#  include <sys/io.h>
# endif

/* Libc5 */
# ifdef HAVE_UNISTD_H
#  include <unistd.h>
# endif

// Read a byte from port
static inline int port_in (unsigned short int port) {
    return inb(port);
}

// Write a byte 'val' to port
static inline void port_out (unsigned short int port, unsigned char val) {
    outb(val, port);
}

// Get access to a specific port
static inline int port_access (unsigned short int port) {
    return ioperm(port, 1, 255);
}

// Get access to 3 ports: port (CONTROL), port+1 (STATUS) and port+2 (DATA)
static inline int port_access_full (unsigned short int port) {
    return ioperm(port, 3, 255);
}

// -------------------------------------------------------------
// Use i386_get_ioperm, i386_set_ioperm, inb and outb from <machine/pio.h> (NetBSD&OpenBSD)
#elif defined HAVE_I386_IOPERM_NETBSD && defined HAVE_MACHINE_PIO_H && defined HAVE_MACHINE_SYSARCH_H && defined HAVE_SYS_TYPES_H
#include <sys/types.h>
#include <machine/pio.h>
#include <machine/sysarch.h>

// Read a byte from port
static inline int port_in (unsigned short int port) {
    return inb(port);
}

// Write a byte 'val' to port
static inline void port_out (unsigned short int port, unsigned char val) {
    outb(port, val);
}

static inline void setaccess(u_long * map, u_int bit, int allow) {
    u_int           word;
    u_int           shift;
    u_long          mask;

    word = bit / 32;
    shift = bit - (word * 32);

    mask = 0x000000001 << shift;
    if (allow)
        map[word] &= ~mask;
    else
        map[word] |= mask;
}

// Get access to a specific port
static inline int port_access (unsigned short int port) {
    u_long          iomap[32];

    if (i386_get_ioperm(iomap) == -1) return -1;

    setaccess(iomap, port  , 1);

    if (i386_set_ioperm(iomap) == -1) return -1;

    return 0;
}

// Get access to 3 ports: port (CONTROL), port+1 (STATUS) and port+2 (DATA)
static inline int port_access_full (unsigned short int port) {
    u_long          iomap[32];

    if (i386_get_ioperm(iomap) == -1) return -1;

    setaccess(iomap, port  , 1);
    setaccess(iomap, port+1, 1);
    setaccess(iomap, port+2, 1);

    if (i386_set_ioperm(iomap) == -1) return -1;

    return 0;
}

//#endif // defined HAVE_I386_IOPERM_NETBSD && defined HAVE_MACHINE_PIO_H && defined HAVE_MACHINE_SYSARCH_H
// -------------------------------------------------------------
// Use i386_get_ioperm, i386_set_ioperm from <machine/sysarch.h> and inb and outb from <machine/cpufunc.h> (FreeBSD)
#elif defined HAVE_I386_IOPERM_FREEBSD && defined HAVE_MACHINE_CPUFUNC_H && defined HAVE_MACHINE_SYSARCH_H && defined HAVE_SYS_TYPES_H
#include <sys/types.h>
#include <machine/cpufunc.h>
#include <machine/sysarch.h>
        
// Read a byte from port
static inline int port_in (unsigned short int port) {
        return inb(port);
}
        
// Write a byte 'val' to port
static inline void port_out (unsigned short int port, unsigned char val) {
        outb(port,val);
}
        
// Get access to a specific port
static inline int port_access (unsigned short int port) {
        return i386_set_ioperm(port, 1, 1);
}

// Get access 3 to ports: port (CONTROL), port+1 (STATUS) and port+2 (DATA)
static inline int port_access_full (unsigned short int port) {
        return i386_set_ioperm(port, 3, 1);
}

//#endif // defined HAVE_I386_IOPERM_FREEBSD && defined HAVE_MACHINE_SYSARCH_H
// -------------------------------------------------------------
// Last chance! Use /dev/io and i386 ASM code (BSD4.3 ?)
#else

// Read a byte from port
static inline int port_in (unsigned short int port) {
    unsigned char value;
    __asm__ volatile ("inb %1,%0":"=a" (value)
                            :"d" ((unsigned short) port));
    return value;
}

// Write a byte 'val' to port
static inline void port_out (unsigned short int port, unsigned char val) {
    __asm__ volatile ("outb %0,%1\n"::"a" (val), "d" (port)
         );
}

// Get access to 3 ports: port (CONTROL), port+1 (STATUS) and port+2 (DATA)
static inline int port_access_full (unsigned short int port) {
    static FILE *  port_access_handle = NULL ;

    if( port_access_handle
        || (port_access_handle = fopen("/dev/io", "rw")) != NULL ) {
        return( 0 );  // Success
    } else {
        return( -1 );  // Failure
    };

    return -1;
}

// Get access to a specific port
static inline int port_access (unsigned short int port) {
    return port_access_full(port); // /dev/io gives you access to all ports.
}

#endif

/*
#else
#include <pc.h>

static inline int
port_in (int port)
{
    unsigned char value;
    value = inportb ((unsigned short) port);
    return (int) value;
}

static inline void
port_out (unsigned int port, unsigned char val)
{
    outportb ((unsigned short) port, val);
}
#endif
*/

#endif // PORT_H

_@/'

Pagina: 1