Interrupt da tastiera

di il
16 risposte

Interrupt da tastiera

Ciao a tutti, ho un programma con un ciclo infinito tipo
void main(){
	while (1){
		do something;}
dovrei controllare quale lettera della tastiera viene premuta, ma se infilo getch() o bioskey(0) il codice si blocca in attesa della pressione di un tasto, mentre se uso kbhit() il codice va avanti ma occupa un sacco di tempo. Vorrei usare un interrupt che non blocchi il ciclo ma l'unico interrupt da tastiera che ho trovato sul manuale è quello di bioskey o _bios_keybrd ma dagli esempi la chiamata è sempre all'interno del ciclo.
Non c'è un interrupt tipo arduino o pic16xxx che si imposta all'inizio del programma per sospenderlo in caso di evento e riprenderlo alla fine della routine di interrupt?
Grazie a tutti in anticipo!

16 Risposte

  • Re: Interrupt da tastiera

    Stai usando un PC e non un micro. Non puoi giocare con gli interrupt.

    Usa la kbhit() e una Sleep(50) (ovviamente la getchar() se individui la pressione di un tasto)
  • Re: Interrupt da tastiera

    oregon ha scritto:


    Usa la kbhit() e una Sleep(50)
    Ho bisogno che il ciclo non rallenti. Se già la kbhit lo rallenta, figurati un ritardo di 50 secondi!
  • Re: Interrupt da tastiera

    oregon ha scritto:


    Stai usando un PC e non un micro. Non puoi giocare con gli interrupt.
    Una limitazione pazzesca...
  • Re: Interrupt da tastiera

    Ovviamente sei ironico ...

    Gli interrupt hardware li puoi usare solo a livello di "device driver" (in kernel mode), ma non è questo il caso ...

    Il ritardo è di 50 MILLIsecondi ed è necessaria per "addormentare" il thread in modo che il kernel non gli assegni il 100% di CPU.

    La kbhit non rallenta nulla, andiamo ...
  • Re: Interrupt da tastiera

    Se non mi ricordo male (stiamo parlando di preistoria ) gli interrupt del dos dovrebbero essere utilizzabili nel tuo caso particolare, quindi in linea teorica si potrebbe fare. Prova a vedere su stack overflow o in qualche forum di retro-programmazione (quelli che usano dosbox ad esempio).

    In ogni caso ha ragione oregon, tanto uno sleep a fine ciclo lo devi mettere comunque...
  • Re: Interrupt da tastiera

    oregon ha scritto:


    Il ritardo è di 50 MILLIsecondi
    Tu hai usato la sleep e quella va in secondi. Per i millisecondi era delay. In ogni caso, il ciclo lavora sotto il millisecondo quindi non posso usare ritardi di nessun tipo.

    oregon ha scritto:


    La kbhit non rallenta nulla, andiamo ...
    Come sopra, purtroppo rallenta di brutto...

    Il mio ciclo accresce un accumulatore che viene elaborato per produrre un suono, quindi ogni ritardo inutile modifica il pitch del suono. Per questo necessitavo un interrupt esterno al ciclo
  • Re: Interrupt da tastiera

    Weierstrass ha scritto:


    Se non mi ricordo male (stiamo parlando di preistoria )
    Uso un PII a 350 MHz e 64 MB di ram. Dos 7 e TC++ 3.1. Quindi si, è preistoria... Ma dopotutto, pur di stare lontano dalla moglie, ci si inventa di tutto!
  • Re: Interrupt da tastiera

    Comunque un PII a 350 MHz è molto più potente dell'Arduino ... quindi ...
  • Re: Interrupt da tastiera

    Prova questo
    https://stackoverflow.com/questions/40961527/checking-if-a-key-is-down-in-ms-dos-c-c
    
    #include <conio.h>
    #include <dos.h>
    #include <stdio.h>
    
    unsigned char normal_keys[0x60];
    unsigned char extended_keys[0x60];
    
    static void interrupt 
    keyb_int() {
        static unsigned char buffer;
        unsigned char rawcode;
        unsigned char make_break;
        int scancode;
    
        rawcode = inp(0x60); /* read scancode from keyboard controller */
        make_break = !(rawcode & 0x80); /* bit 7: 0 = make, 1 = break */
        scancode = rawcode & 0x7F;
    
        if (buffer == 0xE0) { /* second byte of an extended key */
            if (scancode < 0x60) {
                extended_keys[scancode] = make_break;
            }
            buffer = 0;
        } else if (buffer >= 0xE1 && buffer <= 0xE2) {
            buffer = 0; /* ingore these extended keys */
        } else if (rawcode >= 0xE0 && rawcode <= 0xE2) {
            buffer = rawcode; /* first byte of an extended key */
        } else if (scancode < 0x60) {
            normal_keys[scancode] = make_break;
        }
    
        outp(0x20, 0x20); /* must send EOI to finish interrupt */
    }
    
    static void interrupt (*old_keyb_int)();
    
    void
    hook_keyb_int(void) {
        old_keyb_int = getvect(0x09);
        setvect(0x09, keyb_int);
    }
    
    void
    unhook_keyb_int(void) {
        if (old_keyb_int != NULL) {
            setvect(0x09, old_keyb_int);
            old_keyb_int = NULL;
        }
    }
    
    int
    ctrlbrk_handler(void) {
        unhook_keyb_int();
        _setcursortype(_NORMALCURSOR);
        return 0;
    }
    
    static
    putkeys(int y, unsigned char const *keys) {
        int i;
        gotoxy(1, y);
        for (i = 0; i < 0x30; i++) {
            putch(keys[i] + '0');
        }
    }
    
    void
    game(void) {
        _setcursortype(_NOCURSOR);
        clrscr();
        while(!normal_keys[1]) {
            putkeys(1, normal_keys);
            putkeys(2, normal_keys + 0x30);
            putkeys(4, extended_keys);
            putkeys(5, extended_keys + 0x30);
        }
        gotoxy(1, 6);
        _setcursortype(_NORMALCURSOR);
    }
    
    int
    main() {
        ctrlbrk(ctrlbrk_handler);
        hook_keyb_int();
        game();
        unhook_keyb_int();
        return 0;
    }   
    
    Buon divertimento
  • Re: Interrupt da tastiera

    oregon ha scritto:


    Comunque un PII a 350 MHz è molto più potente dell'Arduino ... quindi ...
    E' da lì che è partita la mia idea!!!!

    Weierstrass ha scritto:


    Prova questo
    https://stackoverflow.com/questions/40961527/checking-if-a-key-is-down-in-ms-dos-c-c
    [/code]

    Mitticco! Due giorni a cercare come un pirla e non ho trovato niente e tu lo hai trovato in 10 minuti...
    Stasera vedo se riesco a capirne il funzionamento e provo!
    Grazie!
  • Re: Interrupt da tastiera

    L'hook sul vettore di gestione della tastiera e l'input diretto dalla porta 0x60 lo puoi fare SOLO in DOS (e probabilmente in Windows prime versioni non NT) e, in realtà, non apporta alcuna miglioria di tempo rispetto al controllo della tastiera con la kbhit e il vettore standard...
  • Re: Interrupt da tastiera

    oregon ha scritto:


    L'hook sul vettore di gestione della tastiera e l'input diretto dalla porta 0x60 lo puoi fare SOLO in DOS
    Si, sto lavorando in dos

    oregon ha scritto:


    e, in realtà, non apporta alcuna miglioria di tempo rispetto al controllo della tastiera con la kbhit e il vettore standard...
    Azz...
  • Re: Interrupt da tastiera

    Ieri sera sono riuscito a fare la prova con la routine di Weierstrass. Purtroppo gli errori che mi ha reso erano più delle righe di codice che ho scritto. In ogni caso usando ho provato usando inp(0x60) e funziona perfettamente senza ritardi...
  • Re: Interrupt da tastiera

    Quindi puoi monitorare semplicemente il cambio del valore della porta per sapere quando premi la tastiera.

    Strano che non funzioni l'interrupt. Che poi non funzioni tutto il codice direi che è normale amministrazione nella retro-programmazione, ma purtroppo devi vedertela da solo.

    Comunque è vero che il PC è molto più veloce, ma hai un sistema operativo di mezzo che introduce ritardi non deterministici di mezzo come puoi vedere, quindi non è sempre un vantaggio
Devi accedere o registrarti per scrivere nel forum
16 risposte