/**************************************************************************/
/* test11 - demonstrate IRQ handling                                      */
/**************************************************************************/

#include "rtos.h"
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>


bq_str *bq = NULL;          /* byte queue to hold input */

void interrupt (*oldisr)() = NULL;
thread_x *kbd_thread;

#define DATA_PORT 0x60
#define CTL_PORT  0x61
#define ACK       0x80
#define KBDIRQ    1

/************************************************************************/
/* my_isr - a simple keyboard handler                                   */
/************************************************************************/

void interrupt my_isr(void)
{
    BYTE data, ctl;
    BYTE nop;

    /* read the data */
    data = inportb( DATA_PORT );

    /* strobe the ACK signal */
    ctl = inportb( CTL_PORT );
    outportb( CTL_PORT, ctl | ACK );

    nop ++;     /* need to do something for a tiny delay */
    outportb( CTL_PORT, ctl );

    /* now queue that data */
    bq_sendbyte( bq, data );

    /* send End of Interrupt (EOI) to the controller */
    outportb( 0x20, 0x20 );

}

/************************************************************************/
void isr_setup( void )
{
    /* the keyboard is on IRQ 1 */
    oldisr = rt_enableirq( KBDIRQ, my_isr );
}

/************************************************************************/
void isr_shutdown( void )
{
    /* normally we would use rt_disableirq, but instead we want to
     * return to the ISR handler in place before we started, so we
     * do that with rt_enableirq() and the original handler
     */
    rt_enableirq( KBDIRQ, oldisr );
}

/************************************************************************/
void keyboard(DWORD arg)
{
    BYTE x;

    /* this message automatically gets sent when we terminate */
    kmessage_on_exit( NULL, /* parent */
                      EMSG_THREAD_DEAD,
                      0L );

    do {
        bq_readbyte( bq , &x );
        cprintf( "Key %02x was %s\r\n",
            (x & 127), (x & 128) ? "released" : "pressed");

        /* exit on ESC, key 1 */
        if (( x & 127) == 1 ) {
            cputs("ESC... time to exit");
            return;     /* note: this sends the termination message */
        }
    } while ( 1 );

}

main()
{
    int value;
    long data;


    rt_init(100);
    bq = bq_alloc( 100 );

    kbd_thread = rt_newthread( keyboard, 2,4096, 0, "keyboard thread" );

    cputs("Press keys and see what codes we get, Esc to exit\r\n");

    isr_setup();

    /* message gets sent automatically when thread exits - see thread code */
    kreadmessage( &value, &data );

    isr_shutdown();
}
