Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[OS] [C++] Klawiatura - niepoprawny zestaw znaków? + IRQ1 'nie chce' sie wywoływać

Ostatnio zmodyfikowano 2014-03-09 15:16
Autor Wiadomość
kubawal
Temat założony przez niniejszego użytkownika
[OS] [C++] Klawiatura - niepoprawny zestaw znaków? + IRQ1 'nie chce' sie wywoływać
» 2014-03-04 16:17:09
Witojcie!

Ostatnio pisze sobie małego OS'ika przy pomocy http://pl.wikibooks.org/wiki​/Pisanie_OS/ oraz wiki.osdev.org.
Od razu zaznaczam, że robię to nie dlatego, że chcę zostać kolejnym Billem Gatesem (a zresztą kto chciał by być taką ****** :),
czy pojść w ślady "programistów" Pionner.OS'a, tylko nauczyć się asm'a i low-level'owego c++.

Problem jest taki: jestem w momencie pisania obsługi klawiatury i wszystko niby fajnie działa, ale kody nieprawidłowo sie konwertują.
Używam set'u 2 z dokumentacji na osdev'ie. Podejrzewam, ze obsługę 2 set'a trzeba jakoś ustawić (ale gościu w tutorialu na wikibooks nic o tym nie pisze).
Np kiedy wstukam w klawiaturę
asdfghjkl[Enter]
 to na ekranie wyskakuje mi
~~cxde43~w
(te ~ oznaczają znak, który w set'ie nie jest określony)
Oto funkcja konwertująca kody (zdefiniowane za pomocą enum-a) na odpowiadający mu znak ASCII) (dla kodów 'make', kody 'break' są przechwytywane)
C/C++
char mosKbdToASCII( Key k, unsigned st ) // st - stan klawiatury
{
    const int maxKeynum = 0x66; // maksymalny zaimplementowany klawisz
    if( st &( unsigned ) KbdState::Shift )
    {
        // z klawiszem shift
        static char shiftMp[ maxKeynum + 1 ] =
        {
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, '\t', '~', 0, 0, 0, 0, 0,
            'Q', '!', 0, 0, 0, 'Z', 'S', 'A', 'W', '@',
            0, 0, 'C', 'X', 'D', 'E', '$', '#', 0, 0,
            ' ', 'V', 'F', 'T', 'R', '%', 0, 0, 'N',
            'B', 'H', 'G', 'Y', '^', 0, 0, 0, 'M', 'J',
            'U', '&', '*', 0, 0, '<', 'K', 'I', 'O', ')',
            '(', 0, 0, '>', '?', 'L', ':', 'P', '_', 0,
            0, 0, '\"', 0, '{', '+', 0, 0, 0, 0,
            '\n', '}', 0, '|', 0, 0, 0, 0, '\b'
        };
        if(( int ) k > maxKeynum + 1 )
             return 0;
        else
             return shiftMp[( int ) k ];
       
    }
   
    static char mp[ maxKeynum + 1 ] =
    {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, '\t', '`', 0, 0, 0, 0, 0,
        'q', '1', 0, 0, 0, 'z', 's', 'a', 'w', '2',
        0, 0, 'c', 'x', 'd', 'e', '4', '3', 0, 0,
        ' ', 'v', 'f', 't', 'r', '5', 0, 0, 'n',
        'b', 'h', 'g', 'y', '6', 0, 0, 0, 'm', 'j',
        'u', '7', '8', 0, 0, ',', 'k', 'i', 'o', '0',
        '9', 0, 0, '.', '/', 'l', ';', 'p', '-', 0,
        0, 0, '\'', 0, '[', '=', 0, 0, 0, 0,
        '\n', ']', 0, '\\', 0, 0, 0, 0, '\b',
    };
   
   
   
    if(( int ) k > maxKeynum + 1 )
         return 0;
    else
         return mp[( int ) k ];
   
}

// funkcje do wyświetlania
Key mosReadKey()
{
    // mosReadKbd() wczytuje dane z klawiatury, bez timeout'u
    // kbdBuf to prosta kolejka
    if( kbdBuf.empty() ) // jeśli nie ma żadnego klawisza w buforze
    {
        Key k = mosReadKbd();
        while( !processKey( k ) || k == Key::None )
             k = mosReadKbd();
       
        return k;
    }
    else
         return kbdBuf.pop();
   
}

char mosReadChar()
{
    Key k = mosReadKey();
    return mosKbdToASCII( k, kbdSt );
}

Jeszcze pytanko: niby klawiatura działa, ale jeśli próbuję uruchomić IRQ1 dla lepszej wydajności, to nie działa:
C/C++
// dodaje wpis do IDT
#define _set_gate(gate_addr,type,dpl,addr) \
      __asm__ __volatile__("movw %%dx,%%ax\n\t" \
            "movw %0,%%dx\n\t" \
            "movl %%eax,%1\n\t" \
            "movl %%edx,%2\n\t" \
            : :"i"((short)(0x8000+(dpl<<13)+(type<<8))), \
              "o"(*((char *)(gate_addr))), \
              "o"(*(4+(char *)(gate_addr))), \
              "d"((char *)(addr)),"a"(0x00080000)) \
 

void mosSetIntGate( int n, void * p ) // rejestruje przerwanie
{
    _set_gate( & mosIDT[ n ], 14, 0, p );
}

// włącza przerwanie sprzętowe o podanym numerze
void mosEnableIRQ( unsigned int irq )
{
    unsigned int mask = ~( 1 << irq );
    cached_irq_mask &= mask;
    if( irq & 8 ) {
        mosWritePort( cached_A1, 0xA1 );
    } else {
        mosWritePort( cached_21, 0x21 );
    }
}

#define ASMCALL extern "C" // żeby uniknąć zmiany nazw funkcji przez c++

// a przy inicjowaniu klawiatury
ASMCALL void doIrq1() // przerwanie klawiatury
{
    Key k =( Key ) mosReadPort( KBD_DATA_PORT );
    if( processKey( k ) ) kbdBuf.push( k );
    //mosWriteString("doIrq1()\n");
}

ASMCALL void irq1(); // asm'owa funkcja przerwania

void mosInitKbd()
{
    kbdSt = 0;
    while( !kbdBuf.empty() ) kbdBuf.pop(); // wyczyśc bufor
   
    mosSetIntGate( 0x21,( void * ) irq1 ); // przypisz przerwanie do odpowiedniego adresu
    mosEnableIRQ( 1 );
}
Tak, przekierowałem przerwania sprzętowe, procedurę której do tego użyłem można zobaczyć tutaj
P-105627
MrPoxipol
» 2014-03-05 20:36:22
<< removed >>

/edit: Ja to bym to u góry usunął..

@down:
/edit2: @pekfos, co masz na myśli?
To Alueril :P
P-105688
Elaine
» 2014-03-06 00:50:06
P-105718
kubawal
Temat założony przez niniejszego użytkownika
» 2014-03-06 16:19:14
Przecież napiałem, że korzystałem z wiki.osdev.org, z tego artykułu także (a w sumie to głównie z niego)
Wszystko w moim kodzie się z nim zgadza.

/edit: przeczytałem także o tym, że niektóe klawiatury translate'ują na set 1, ale nie moja.
/edit2: @pekfos, co masz na myśli?
P-105742
kubawal
Temat założony przez niniejszego użytkownika
» 2014-03-06 17:34:58
A może trzeba jawnie ustawić set 2? (za pomocą komendy F0)
(chociaż przecież wszystkie nie-prehistoryczne klawiatury mają domyślnie ustawiony set 2)
P-105751
Elaine
» 2014-03-06 17:44:08
Note: Normally on PC compatible systems the keyboard itself uses scan code set 2 and the keyboard controller translates this into scan code set 1 for compatibility.

Popatrz dokładnie na wartości, które dostajesz od kontrolera klawiatury i porównaj z wartościami z setów pierwszego i drugiego.
P-105752
kubawal
Temat założony przez niniejszego użytkownika
» 2014-03-07 16:41:09
Próbowałem wyłączyć translacje, wtedy kody sie zmieniają i wciskane znaki wyświetlają się podwójnie.

Co do porównania setów 1 i 2 to znaki te nie pasują do żadnego z nich zarówno przed jak i po translacji.
P-105804
Brezniew
» 2014-03-07 23:41:54
Jakiego emulatora używasz?
I jeśli używasz C++ to lepiej przepisz kod do C w C++ jest zaimplementowanych wiele rzeczy do których obsługi wymagana jest biblioteka standardowa C++, a w c wszystko generowane jest przez kompilator. Pisanie głównego kodu w c powoduje wiele błędów, a niektóre, elementy są niemożliwe lub niepraktyczne do zaprogramowania.
P-105824
« 1 » 2 3
  Strona 1 z 3 Następna strona