** 1 page regular EJP Series Part 3 / 922 words ** ** On Reader disk logo ** Reading, Writing and Arithmetic In this issue Xav takes a look at the code needed to read a joypad... To briefly recap, last time we looked at how the joypad manages to code lots of switches onto only a few connections using a system called multiplexing. This is achieved by taking one of four input lines low and sending the corresponding switch information to the output via some Schmitt triggered buffers. Therefore in order to read the overall status of a joypad, our software routine has to take each of the input lines low in turn and read the output at each stage. Input lines on the joypad correspond to output lines from the computer, and vice versa. This means our code has to write a value to the computer's output lines, then read a value from its input lines before moving on to write another value to the output lines. To read the overall status of a joypad these steps have to be repeated four times - but it gets worse! Under supervision In an ideal world we would simply use a call and ask the operating system: "Oi! Could you fill this area of memory with the joypad status please?" However, there are no operating system calls to deal with the joypads, so we have to implement them manually. If you're thinking it can't get any worse it can! - the EJPs addresses lie in hardware at addresses which can't easily be accessed from a C program! The way around this obstacle is to fool the microprocessor into believing we're actually part of the operating system - which is easier than it sounds! The 68k series of processors at the heart of STe and Falcon machines provide a concept of "user" and "supervisor" modes - the idea being the OS works in supervisor mode, running applications in the more restrictive user mode. This is designed to prevent programs doing anything nasty without the processor realising what's happening. In order to directly access the EJP memory addresses we need to switch the CPU into supervisor mode, which is done using one of two OS functions provided. The first, Supexec(), is an Xbios call which is used to execute a whole function in supervisor mode. The second, Super(), is used to switch into and out of supervisor mode within a function. Since applications should remain in user mode we'll use the Super() call just when we need it. To enter supervisor mode call Super() with a NULL parameter and the function will return a pointer to the old supervisor stack pointer, which we store to use as a parameter later on. Don't worry if you're not sure how to handle pointers and stack pointers, the code on the Reader disk handles everything for you. It's still worth browsing the file to familiarise yourself with how to use Super(). On completing our task in supervisor mode we recall Super() passing the pointer we saved earlier as a parameter - which enables the processor to carry on where it left off. Bits and pieces Now we know how to switch into supervisor mode, the rest is relatively straightforward. The address of the EJP output lines is 0xFF9202 so we can write a mask to this address with one of the bits set to zero - pulling the corresponding multiplexer line low. These masks are defined in the file "masks.h" on the Reader disk. Once the mask has been written, we can read the input lines to see which switches in the selected group are being pressed. This information is split across two addresses with 0xFF9200 containing the fire-buttons, option, pause details while the upper bits of 0xFF9202 contain details of the numeric keypad. Here's an example, if we write a mask of 0xFFFE to test group 1, then bit 0 of 0xFF9200 corresponds to fire-button A on the joypad in port A and bit 1 is the PAUSE button for port A. Bit 2 is firebutton A for port B and bit 3 is the PAUSE button for port B. Similarly if we read 0xFF9202 we will find bit 8 corresponds to UP on port A, bit 9 is DOWN on A, bit 10 is LEFT and bit 11 is RIGHT. Bits 12 to 15 represent the same data for port B. However, because the mask only activates the multiplexer line for port A, the bits for port B will all be HIGH - remember bits are taken LOW if buttons are being pressed. ** Caption ** table_1.gem The bitmask information returned by joypads ** end caption ** This information is summarised in the table and also defined in "ejp.h" on the Reader disk. By way of an example, this file also contains a function to read all the buttons on a joypad in port A and fill in a structure (defined in "ejp_defs.h") accordingly. Using a function like this is quite straightforward, simply pass it the address of a suitable structure then make use of the data. As a first step you might like to try printing out the joypad status, and the file "pad_1.c" on the Reader disk is a simple program which does exactly that. In the next exciting instalment... By far the best way to get a feel for the joypad code is to play around with it so I'll leave you to adapt and modify the code. Next time we'll look at a few tricks which speed up reading the joypad and take look at the 26 button Procontroller.