volatile int * ptr_ps2 = 0x40000000;
char read_key() {
char status;
char key;
while (1) {
status = *(ptr_ps2);
while ((status & 0x1) == 1) {
status = *(ptr_ps2);
}
key = *(ptr_ps2 + 1);
if (key == 0xF0) {
status = *(ptr_ps2);
while ((status & 0x1) == 1) {
status = *(ptr_ps2);
}
key = *(ptr_ps2 + 1);
clear_display(0);
return key;
}
}
}
Mit kell tudni: ptr_ps2 egy ps2 periféria státuszregiszterére mutat. Alsó bitje 1, ha a fogadó FIFO üres. *(ptr_ps2+1)-ból olvasva pedig kiveszed a FIFO-ból az aktuális karaktert (ha empty, akkor szemetet).
A PS/2 periféria működése: billentyű nyomvatartásakor a karakter ASCII kódját (átfordítja SCAN kódból) teszi a FIFO-ba, utána felengedéskor egy 0xf0 értéket, utána megint a karakter ASCII kódját.
Tünet: sosem lép ki a függvény, hiába nyomja az ember a billentyűket.
UI: van spoiler-tag a HUP-on? Leírnám a megoldást is :-)
- wachag blogja
- A hozzászóláshoz be kell jelentkezni
- 1546 megtekintés
Hozzászólások
A státusz kiolvasás egyben az adatot is kiolvassa? (mert pl a char szélesebb az adott környezetben, mint 8 bit?)
Üdv,
Marci
- A hozzászóláshoz be kell jelentkezni
Nem, a char 8 bit, de ügyes gondolat. Maga a proci amúgy 32 bites, big endian MicroBlaze a teljesség kedvéért.
- A hozzászóláshoz be kell jelentkezni
Nem a
volatile int * ps2_status = 0x40000000;
sorral van a gond? Szerintem ennek kéne lennie:
volatile char * ps2_status = 0x40000000;
- A hozzászóláshoz be kell jelentkezni
Nem, az teljesen jó (bár javítva ps2_ptr-re), a busz is 32 bites. A key-be meg a status-ba pont a lényeges dolgok kerülnek.
- A hozzászóláshoz be kell jelentkezni
Barkochba ér? Az az érzésem, hogy a (key == 0xF0) sose lesz igaz valamiért, pedig eljut odáig. Rosszfelé járok?
Üdv,
Marci
- A hozzászóláshoz be kell jelentkezni
Jófelé.
- A hozzászóláshoz be kell jelentkezni
Mert a 0xF0 akkor kerül a key-be, amikor az if belsejében olvassuk ki a következő karaktert, amit viszont sose nézünk nem-e 0xF0?
Szerk: Ez egy marhaság pls ignore (de mekkora! :D - látszik, hogy okostelefonon nem látszik egyben minden - tán akkor nem írok ekkora hülyeséget)
Üdv,
Marci
- A hozzászóláshoz be kell jelentkezni
A 0xF0 az +240 (integer konstans, legalább 16 bit előjeles konstans, platformfüggő, hogy pont hány).
Ha ezt beleteszem egy előjeles char-ba, aztán visszaalakja a program implicite (signed)int-té az összehasonlításhoz, az már -16, tehát nem egyenlők.
Ez amúgy nem is teljesen C specifikus, hasonló szívásokat Java-ban is el lehet követni.
- A hozzászóláshoz be kell jelentkezni
Ön nyert :-).
De ha 0xfffffff0-lal hasonlítjuk össze, akkor már megy is szépen.
- A hozzászóláshoz be kell jelentkezni
Szép. Kár, hogy sose láttam C-t közelről :)
Üdv,
Marci
- A hozzászóláshoz be kell jelentkezni
Amúgy nagy élményt szerzett nekem is, szeretem, amikor ilyenek jönnek hallgatói kódokból.
- A hozzászóláshoz be kell jelentkezni
:D
Ezt szerettem én is a tanításban. Meg a jó kérdéseket, amik annyira relevánsak az adott helyen, mintha csak megbeszéltük volna a táncrendet. :)
Amúgy sejtettem, hogy a C típuskezelése körül lesz a megoldás, de a tudás hiánya megakadályozott, hogy megtaláljam :)
Üdv,
Marci
- A hozzászóláshoz be kell jelentkezni
...vagy az ismeretlen tartalmú clear_display() sose tér vissza valamiért.
Üdv,
Marci
- A hozzászóláshoz be kell jelentkezni
Annyira szemét nem vagyok, hogy ilyet adjak fel. A feladvány teljesen specifikált ;-)
- A hozzászóláshoz be kell jelentkezni
C-től borsódzik a hátam, de:
int pointer-t derefel és tárolja el egy char-ba (gondolom a fordító azért minimum warningolt rá... remélem).
A másik tipp, hogy a PS/2 vezérlő nem várja meg a 0xF0 ellenőrzés előtti kiolvasást, hanem addigra visszaírta a karakter kódját, úgyhogy visszalép a ciklusba.
BlackY
--
"en is amikor bejovok dolgozni, nem egy pc-t [..] kapcsolok be, hanem a mainframe-et..." (sj)
- A hozzászóláshoz be kell jelentkezni
Nem warningol rá (ejnye-bejnye), de amúgy a char-ba pontosan az kerül, ami kell, a felsőbb bitek eldobhatók.
- A hozzászóláshoz be kell jelentkezni
A ptr_ps2 hol kap értéket?
- A hozzászóláshoz be kell jelentkezni
Fixed, elírás volt a postban.
- A hozzászóláshoz be kell jelentkezni
Csak egy tipp: Az if elojeles es nem elojeles valtozokra maskepp mukodik a fordító miatt.
Nah egy kis update egy kis peldaval:
#include <stdio.h>
int main(){
unsigned char key;
char elojeles_key;
key = 0xF0;
elojeles_key = 0xF0;
if (key == 0xF0)
{
printf("Key jol mukodik\n");
}
else
{
printf("Key nem jol mukodik\n");
}
if (elojeles_key == 0xF0)
{
printf("Elojeles key jol mukodik\n");
}
else
{
printf("Elojeles key nem jol mukodik\n");
}
}
Ami lefordítva és futtatva a következőt adja:
~$ gcc elojeles.c -o elojeles
~$ ./elojeles
Key jol mukodik
Elojeles key nem jol mukodik
~$
Ha szétvesszük a forrást két részre külön-külön lefordítjuk, hogy lássuk mit is csinál a fordító, akkor a fordítás után ezt kapjuk az előjelnélküli változó használata esetén::
.file "nem_elojeles.c"
.section .rodata
.LC0:
.string "Key jol mukodik"
.LC1:
.string "Key nem jol mukodik"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
movb $-16, 31(%esp)
cmpb $-16, 31(%esp)
jne .L2
movl $.LC0, (%esp)
call puts
jmp .L4
.L2:
movl $.LC1, (%esp)
call puts
.L4:
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Debian 4.7.2-5) 4.7.2"
.section .note.GNU-stack,"",@progbits
Ez nagyjából úgy néz ki, mint amit egy ember is írna. A feltétel teljesülésének vizsgálatát a cmpb végzi és jne ugrással megy az else ágra.
Előjeles változó definiálása esetén másképp néz ki a dolog:
.file "elojeles.c"
.section .rodata
.LC0:
.string "Elojeles key nem jol mukodik"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
movb $-16, 31(%esp)
movl $.LC0, (%esp)
call puts
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Debian 4.7.2-5) 4.7.2"
.section .note.GNU-stack,"",@progbits
Ami elsőre feltűnik, hogy az "Elojeles key jol mukodik" hianyzik,ez pedig azt jelenti, hogy bizony itt valami okossággal van dolgunk. Ahogy hiányzik a cmpb is, helyette csak egy call hívás van a printf-hez. Bizony, a fordítónk kioptimalizálta a kódunkat.
De ez csak okoskodás, mert nem vagyok programozó, és C-hez sem értek.
--
"Maradt még 2 kB-om. Teszek bele egy TCP-IP stacket és egy bootlogót. "
- A hozzászóláshoz be kell jelentkezni
Megoldás fentebb, kettes komplemens, előjelkiterjesztés. Jópofa dolog.
- A hozzászóláshoz be kell jelentkezni
Igen. Csak meg jopofabb lenne, ha a hiba azonos, vagy kozel azonos kodot eredmenyezne forditasnal. Az ilyentol erosen kopik az ember haja.
--
"Maradt még 2 kB-om. Teszek bele egy TCP-IP stacket és egy bootlogót. "
- A hozzászóláshoz be kell jelentkezni
A jópofát úgy értem, hogy az oktatásban (!=ipar) a debug rejtvényfejtést jelent, nincs akkora nyomás feletted, hogy meg kell oldani. Így szerethetek debugolni, mert az gondolkodást igényel esetenként.
- A hozzászóláshoz be kell jelentkezni
Én hülye vagyok a C-hez, de én azt a "while (1)" részt írnám át.
[ Falu.me ]
- A hozzászóláshoz be kell jelentkezni
Adatfolyam olvasasara altalaban (mindig?) vegtelen ciklust szoktak alkalmazni, amibol ha mar nincs ra szokseg, ki lehet break()-elni.
Szerk: termeszetesen eleg low-levelig visszamenve. Az hogy egy high-level nyelv ezt elrejti, az mas kerdes.
- A hozzászóláshoz be kell jelentkezni
De csak a key == 0xF0 esetén van return, szóval az az ág ki sem értékelődik, így máshogy nem tud kilépni. De lehet, hogy már az if előtti while ciklusba keveredik bele, mint macska pöcse a kenderkócba.
[ Falu.me ]
- A hozzászóláshoz be kell jelentkezni