OS-9/OSK Answers! by Joel Mathew Hegberg
June 1994 issue


I just got back from the Chicago CoCo/OS-9 Fest a couple days ago, and it's amazing how energized and excited you can get by attending one of those shows! For those of you who could not make it, a complete report of the fest will soon be available (if it's not already). We have some wonderful OS-9 vendors selling great hardware and software. New, affordable OS-9/68000 systems should be coming out sometime soon and that's really exciting.

In this issue, I would like to first cover new discoveries into the MM/1's keyboard driver by Andrzej Kotanski, investigate how to read the system time under OS-9, and close with some notes about OS-9 signals.

For a long time now, MM/1 programmers have been discussing ways to improve the K-Windows keyboard driver (keydrv) to allow more functionality and full distinction amongst all keys. Certain programs (most notably KBCom, by Eddie Kuns) require such functionality before being released. Andrzej has discovered that when the CONTROL, ALT, SHIFT, NUM LOCK, SCROLL LOCK, or CAPS LOCK are being pressed, certain bits in the K-Windows data memory module, wdata, are set. This opens up many new possibilities f or MM/1 programmers. I've already written a screen-saver program which takes advantage of this, and Eddie Kuns is planning on using this functionality in KBCom. Listing #1 contains Andrzej's source code.

Listing #1: kysns.c
===================
/* kysns.c - program to check certain MM/1 keys -
   released to PD by Andrzej Kotanski, April 24, 1994   */

/* scroll lock is used to disable middle mouse button copying  */
/* run the test program after typing 'tmode nopause'           */

main()
{
    while (1)
       kysns();
}

char *wdata = 0;
char *keydata;
extern errno;
kysns()
{
    if ( wdata == 0 )
    {
        wdata = (char *)modlink("wdata", 1024);
        if ( wdata == (char *)-1 )
           exit(errno);
        keydata = wdata + 0xb4;
    }

    if ( keydata[2] & 1 )
       printf("left_shift ");
    if ( keydata[2] & 2 )
       printf("right_shift ");
    if ( keydata[3] )
       printf("scroll");
    if ( keydata[4] )
       printf("control ");
    if ( keydata[5] )
       printf("alt ");
    if ( keydata[6] )
       printf("capslock ");
    if ( keydata[7] )
       printf("numlock ");
    if ( keydata[8] )
       printf("capslock2 ");
    if ( keydata[9] )
       printf("numlock2 ");
    if ( keydata[10] )
       printf("if_you_got_this_please_tell_the_author ");
    printf("\n");
}

Some people find it difficult to read the system time using C under OS-9. I don't see why this should be a problem... I mean, just use the call to get the current system time and there you go, right? Hmmm... Let's look in the OS-9 C manual and see which calls deal with time. _sysdate(), _julian(), asctime(), ctime(), localtime(), mktime(), clock(), difftime(), getime(), gmtime(), setime(), and time()... and each call represents time in various formats. Well, ok, maybe I can see where the trouble is coming from! Certainly, since we're running a real-time operating system, we need to get this confusion taken care of!

I usually use the getime() function because it's so easy to use. This call gives you the system year, month, day, hours, minutes, and seconds. This appears to be the easiest call to use under OS-9. The structure for the time being returned is defined in the header file 'time.h', so be sure to include that in any programs using the getime() function.

Listing #2 gives a simple example of how to use the getime() function to return the current system time to your program. Notice that we pass the address of (i.e. a pointer to) our time structure to the getime() function so it can fill in the required data, which is why we use the ampersand (&) character in front of the timebuf structure.

Listing #2: showtime.c
======================
#include <stdio.h>
#include <time.h>

struct sgtbuf timebuf;

main()
{
    getime(&timebuf);
    printf("Year:  %d\n", timebuf.t_year);
    printf("Month: %d\n", timebuf.t_month);
    printf("Day:   %d\n", timebuf.t_day);
    printf("%d hours\n",  timebuf.t_hour);
    printf("%d minutes\n", timebuf.t_minute);
    printf("%d seconds\n", timebuf.t_second);
}

Another common problem for beginning OS-9 C programmers is signal handling. Signals and signal handlers (also called 'signal traps') are generally new concepts to novice OS-9 C programmers and they usually don't know how to 'install' a signal handler or what should be put into a signal handler. Luckily, the answers are very simple. In fact, the simplicity is at the root of the confusion. You would think there would be a significant amount of source code to be placed into something called a 'signal handler', but this is not the case at all.

A signal is just a value sent to an OS-9 program, hopefully for a special reason. A signal code of 2 or 3 may mean then user has pressed CTRL-C or CTRL-E to abort the program. If your program does not have a signal trap, it will die immediately. If you install a signal trap, your program will be able to continue processing. So in this instance, the signal trap is analogous to the ON BREAK GOTO function in BASIC for preventing a user from killing the program. But this is not the primary reason signal traps are used.

Signal traps are very useful when reading keyboard or mouse information. Perhaps you would like OS-9 to send a signal when the user presses a key or clicks a mouse button. This way your program could go on processing other information while occasionally checking if a signal has been received to read keyboard or mouse data. Optionally, your program may request OS-9 send keyboard/mouse signals and then simply go to sleep indefinitely (using sleep(0); or tsleep(0);). When a signal is received by a sleeping process, the process is awaken so it may process the signal. This frees up the CPU for other processes and prevents processes who are simply waiting for keyboard input from hogging the system's resources.

So, how do you do all this neat stuff? As complex as the above explanation is, the answer is it's amazingly simple. The important point is the signal handler function MUST NOT do any I/O processing or anything complex. That is where most novice OS -9 programmer's run into problems. As a rule of thumb, the signal handler should only save the signal, allowing all processing to be done by the program itself. Listing #3 gives an example of how one may use a signal trap to read the keyboard.

* Note that user-defined signals (such as ones sent back when a keypress is made, etc.) must be in the range of 256-65535 for OS-9/68000 or 128-255 for OS-9/6809.

Listing #3: keyb_signal.c
=========================
#include <stdio.h>

#define STDIN  0

#ifdef OSK
#define KEYSIG 400
#else
#define KEYSIG 140
#endif

extern int signal_handler();
int signal;

main()
{
    char keypress;
    
    /* Install signal trap */
    intercept(signal_handler);
    
    while(1)
    {
        signal = 0;
        
        /* Request signal to be sent by OS-9 when user presses a key, */
        /* then go to sleep indefinitely. */
        _ss_ssig(STDIN, KEYSIG);
        sleep(0);
        
        /* Now, we process the signal... not the signal handler. */
        if (signal == KEYSIG)
        {
            read(STDIN, &keypress, 1);
            printf("\nUser pressed %c key.\n", keypress);
            fflush(stdout);
            if (toupper(keypress) == 'Q')
            {
                printf("Exiting program.\n");
                break;
            }
        }
        else
        {
            printf("\nUnknown signal received: %d\n", signal);
            printf("Exiting program.\n");
            break;
        }
    }
}

/* The parameter to the signal handler is the signal received. */
signal_handler(s)
int s;
{
    signal = s;
}

Any comments or questions may be sent to me in care of this magazine. Best wishes, and see you next issue!

* THE END *