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) char mosKbdToASCII( Key k, unsigned st ) { const int maxKeynum = 0x66; if( st &( unsigned ) KbdState::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 ]; }
Key mosReadKey() { if( kbdBuf.empty() ) { 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: #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 ) { _set_gate( & mosIDT[ n ], 14, 0, p ); }
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"
ASMCALL void doIrq1() { Key k =( Key ) mosReadPort( KBD_DATA_PORT ); if( processKey( k ) ) kbdBuf.push( k ); }
ASMCALL void irq1();
void mosInitKbd() { kbdSt = 0; while( !kbdBuf.empty() ) kbdBuf.pop(); mosSetIntGate( 0x21,( void * ) irq1 ); mosEnableIRQ( 1 ); }
Tak, przekierowałem przerwania sprzętowe, procedurę której do tego użyłem można zobaczyć tutaj |