Techno-Plaza
Site Navigation [ News | Our Software | Calculators | Programming | Assembly | Downloads | Links | Cool Graphs | Feedback ]
 Main
   Site News

   Our Software

   Legal Information

   Credits

 Calculators
   Information

   C Programming

     Introduction to C

     Keyboard Input

       Part I

       Part II

       Part III

     Graphics Intro

     Slider Puzzle 1

     Functions

     Pointers

     Dynamic Memory

     Slider Puzzle 2

     Structures

     Bit Manipulation

     Advanced Pointers

     File I/O

     Graduate Review

   Assembly

   Downloads

 Miscellaneous
   Links

   Cool Graphs

   Feedback Form

C Programming Lessons

TIGCC Programming Lessons

Lesson 2 - Basic Keyboard Input

Step 4 - Reading the Keyboard Directly

As we have seen with the previous examples, ngetchx() is not always the best function to use. It's fine if you are actively waiting for keyboard input (like for a user to press a key to continue), or for small programs that do not require constant keyboard input (things other than action games, mainly), but for big programs that require fast and consistent (nearly constant at times) keyboard reading, ngetchx() simply won't work for us.

Introducing the keyboard queue. This queue is the location in memory where keyboard presses are stored. The system automatically handles the queuing of these key presses, so all we need to do is dequeue them. If you are unfamiliar with queues, here are the basics. The keyboard queue is a FIFO queue, which stands for First In First Out. This means whatever gets queued first will be dequeued first as well. Since the system handles queueing keys for us, all we need to do is check to see if any are ready to be dequeued.

Step 5 - A Simple Example Using OSdequeue()

Start a new TIGCC project. Create a C Source File and name it kbqueue. Edit the file so that it looks like this:

kbdqueue.c


#include <tigcclib.h>

void _main(void) {
    void *kbq = kbd_queue();
    unsigned short key;
    unsigned long count = 0;

    // clear the screen
    clrscr();

    // print the string telling the user to press a key
    printf("Please press a key.\n");

    // while no key was retrieved from the keyboard queue
    while (OSdequeue(&key, kbq)) {
        // increment the variable number by one
        printf("Queue Check: %lu.\n", count);
        ++count;
    }

    // tell them what key they pressed
    printf("The keycode was %hu\n", key);

    // wait for input before exiting
    ngetchx();
}

Step 5a - Compile and Run the Program

We need to take one more minor step before we can compile the program. Certain functions only exist in later revisions of the AMS. Due to an error in the original TI-92+ AMS, we need to set the minimum AMS version to 1.01. If we don't, TIGCC won't let us use the OSdequeue function. Don't worry about the TI-89, as version 1.01 is the same as 1.00 for it.

In the TIGCC IDE, go to Project, Options. Then select the Compilation tab and hit the Program Options button. Choose the Operating System tab now. Select Minimum AMS Version and set it to 1.01. Close the Program Options box and select OK. Now you can build the program and send it to TiEmu.

TI-89 AMS 2.05 kbqueue.89z TI-92+ AMS 2.05 kbqueue.9xz

Step 5b - Analyze the Program

The programs are getting more and more complex, but they should not yet be difficult. There are some new concepts introduces (void pointers, type modifiers, new format specifiers, and two new functions), but don't worry, it'll all be explained.

void *kbq = kbd_queue();

This is a new kind of variable type, the void pointer. A pointer is a place keeper for somewhere in memory. More speficically, a void pointer is a pointer to an address. In our case, our void pointer will be the address of the system keyboard queue. We will use the address of system keyboard queue to read the keyboard later. We will learn more about pointers in later lessons.

unsigned short key;
unsigned long count = 0;

We have some new variable declarations, but they are fairly simple. A short is a short integer, which is 2-bytes in TIGCC. unsigned means there are no negative numbers. Since a byte is 8 bits, and we have 2, we get 2^(8*2)=65,536 possibilities. A signed short would have the range -32,768 to 32,767, and the unsigned short has the range 0 to 65,535. All int variables in TIGCC are by default short unless you change it in the compiler options, which is rarely necessary, but it is best to be specific where possible to avoid complications.

As we have seen, shorts (or short ints) are 2-bytes. longs (or long ints) are 4 bytes. Longs have 2^(8*4)=4,294,967,296 possibilities. A signed long integer has a range of -2,147,483,648 to 2,147,483,647. An unsigned long has a range of 0 to 4,294,967,295.

It is usually fine to just use an int variable. The only times when you need to specify size of signed-ness is when you have a specific range of values you have to capture. The system key codes fall right into the range of a 16-bit unsigned integer, so an unsigned short makes sense here.

In a previous version of this example, the long variable was useful because it often went beyond 65,535 very quickly. In this revised example, it probably won't, but it's still nice to see the opposite of a short.

One more thing to note here is that long and short are not variable types. They are actually type modifiers. Type modifiers are ways to give attributes to certain variable types. In our case, short, long, unsigned, and signed all modify the int variable type. Although you can write out "long int" or "short int", most people don't for brevity's sake.

// clear the screen
clrscr();

// print the string telling the user to press a key
printf("Please press a key.\n");

This code should be obvious by now. We clear the screen and print a string.

// while no key was retrieved from the keyboard queue
while (OSdequeue(&key, kbq)) {
    // increment the variable number by one
    printf("Queue Check: %lu.\n", count);
    ++count;
}

Here is the heart of our program, the OSdequeue function. If you take a look at the TIGCC docs, you will notice that OSdqeueu will return true if the queue is empty. So, while the OSdequeue function returns empty, it means there is no key in the keyboard queue for us to extract.

The body of the loop is simple. But notice the & (ampersand) before the key variable in the OSdqueue function call. This is called the 'address-of' operator. It takes a variable, determines its address in memory, and we get a pointer. We will learn more about pointers later, but for now, it is enough to know that the OSdequeue function will use the pointer to the key variable we gave it to put our key press there if the queue isn't empty.

// tell them what key they pressed
printf("The keycode was %hu\n", key);

// wait for input before exiting
ngetchx();

This is pretty standard stuff. The only remarks I want to make are in regard to the format specifiers used by printf here and in the while loop body. Since we did use an integer variable, we need to use the right kind of specifier for printf to be able to replace the value. %u is the specifier for unsigned integer, like %d was for integer. The h and l in front of the u mean sHort and Long, respectively. We can't use %s, because it's already used for string replacement. If you look in the TIGCC docs for the printf function, the complete syntax for format specifiers is there which can help you out.

Step 5c - Program Conclusions

This program shows us the fastest method for keyboard reading provided to us by the system. However, there are drawbacks here as well. First, we cannot read the modifier keys independently of their combo key, i.e. we can't tell if the user just pressed 2nd or diamond. If you need to do this, you will need to read the keyboard by hand. This will be covered in a later lesson.


Lesson 2: The Basics of Keyboard Input
Questions or Comments? Feel free to contact us.


 

Copyright © 1998-2007 Techno-Plaza
All Rights Reserved Unless Otherwise Noted

Get Firefox!    Valid HTML 4.01!    Made with jEdit