libdragon
Data Structures | Modules | Files | Typedefs | Functions | Variables
Controller Subsystem
libdragon

Controller and accessory interface. More...

Data Structures

struct  SI_condat
 SI Controller Data. More...
struct  controller_data
 Structure for interpreting SI responses. More...

Modules

 Mempak Filesystem Routines
 

Managed mempak interface.


Files

file  controller.c
 

Controller Subsystem.


file  controller.h
 

Controller Subsystem.


Typedefs

typedef struct SI_condat _SI_condat
 SI Controller Data.
typedef struct controller_data _controller_data
 Structure for interpreting SI responses.

Functions

void controller_init ()
 Initialize the controller subsystem.
static void __SI_DMA_wait (void)
 Wait until the SI is finished with a DMA request.
static void __controller_exec_PIF (void *inblock, void *outblock)
 Send a block of data to the PIF and fetch the result.
int eeprom_present ()
 Probe the EEPROM interface.
void eeprom_read (int block, uint8_t *const buf)
 Read a block from EEPROM.
void eeprom_write (int block, const uint8_t *const data)
 Write a block to EEPROM.
void controller_read (struct controller_data *output)
 Read the controller button status for all controllers.
void controller_scan ()
 Scan the controllers to determine the current button state.
struct controller_data get_keys_down ()
 Get keys that were pressed since the last inspection.
struct controller_data get_keys_up ()
 Get keys that were released since the last inspection.
struct controller_data get_keys_held ()
 Get keys that were held since the last inspection.
struct controller_data get_keys_pressed ()
 Get keys that are currently pressed, regardless of previous state.
int get_dpad_direction (int controller)
 Return the DPAD calculated direction.
void execute_raw_command (int controller, int command, int bytesout, int bytesin, unsigned char *out, unsigned char *in)
 Execute a raw PIF command.
int get_controllers_present ()
 Return a bitmask representing which controllers are present.
static int __is_valid_accessory (uint32_t data)
 Return whether the given accessory is recognized.
static void __get_accessories_present (struct controller_data *output)
 Query the PIF as to the status of accessories.
int get_accessories_present ()
 Return a bitmask specifying which controllers have recognized accessories.
static uint16_t __calc_address_crc (uint16_t address)
 Calculate the 5 bit CRC on a mempak address.
static uint8_t __calc_data_crc (uint8_t *data)
 Calculate the 8 bit CRC over a 32-byte block of data.
int read_mempak_address (int controller, uint16_t address, uint8_t *data)
 Read a chunk of data from a mempak.
int write_mempak_address (int controller, uint16_t address, uint8_t *data)
 Write a chunk of data to a mempak.
int identify_accessory (int controller)
 Identify the accessory connected to a controller.
int identify_controller (int controller)
 Identify the controller connected to a controller port.
void rumble_start (int controller)
 Turn rumble on for a particular controller.
void rumble_stop (int controller)
 Turn rumble off for a particular controller.

Variables

static struct SI_regs_s *const SI_regs = (struct SI_regs_s *)0xa4800000
 Structure used to interact with SI registers.
static void *const PIF_RAM = (void *)0x1fc007c0
 Location of the PIF RAM.
static struct controller_data current
 The current sampled controller data.
static struct controller_data last
 The previously sampled controller data.

SI status register bit definitions

#define SI_STATUS_DMA_BUSY   ( 1 << 0 )
 SI DMA busy.
#define SI_STATUS_IO_BUSY   ( 1 << 1 )
 SI IO busy.

Bitmasks for controller status

See also:
get_controllers_present
get_accessories_present
#define CONTROLLER_1_INSERTED   0xF000
 Controller 1 Inserted.
#define CONTROLLER_2_INSERTED   0x0F00
 Controller 2 Inserted.
#define CONTROLLER_3_INSERTED   0x00F0
 Controller 3 Inserted.
#define CONTROLLER_4_INSERTED   0x000F
 Controller 4 Inserted.

Accessory ID Values

See also:
identify_accessory
#define ACCESSORY_NONE   0
 No accessory present.
#define ACCESSORY_MEMPAK   1
 Mempak present.
#define ACCESSORY_RUMBLEPAK   2
 Rumblepak present.
#define ACCESSORY_VRU   3
 VRU present.

Controller ID Values

See also:
identify_controller
#define CONTROLLER_NONE   0xFF
 No controller present.
#define CONTROLLER_MOUSE   2
 Mouse present.
#define CONTROLLER_KEYBOARD   4
 Keyboard present.
#define CONTROLLER_PAD   5
 Digital pad present.

SI Error Values

#define ERROR_NONE   0x0
 No error occured.
#define ERROR_BAD_COMMAND   0x1
 Command not recognized or malformed.
#define ERROR_NOT_PRESENT   0x2
 Controller not present.

Detailed Description

Controller and accessory interface.

The controller subsystem is in charge of communication with all controllers and accessories plugged into the N64. The controller subsystem is responsible for interfacing with the serial interface (SI) registers to provide controller data, mempak and rumblepak interfacing, and EEPROM interfacing.

Code wishing to communicate with a controller or an accessory should first call controller_init. Once the controller subsystem has been initialized, code can either scan the controller interface for changes or perform direct reads from the controller interface. Controllers can be enumerated with get_controllers_present. Similarly, accessories can be enumerated with get_accessories_present and #identify_accesory.

To read controllers in a managed fashion, call controller_scan at the beginning of each frame. From there, get_keys_down, get_keys_up, get_keys_held and get_keys_pressed will return the status of all keys relative to the last scan. get_dpad_direction will return a number signifying the polar direction that the D-Pad is being pressed in.

To read controllers in a non-managed fashion, call controller_read. This will return a structure consisting of all button states on all controllers currently inserted.

To enable or disable rumbling on a controller, use rumble_start and rumble_stop. These functions will turn rumble on and off at full speed respectively, so if different rumble effects are desired, consider using the Timer Subsystem for accurate timing.

A mempak attached to a controller can be treated in one of two ways: as a raw binary string, or as a formatted mempak with notes. The former allows storage of any data as long as it fits, in any format convenient to the coder, but destroys any non-homebrew data on the mempak. The latter is recommended as it is completely compatible with official N64 games, though it allows less data to be stored due to filesystem overhead. To read and write raw sectors, use read_mempak_address and write_mempak_address. The Mempak Filesystem Routines handles reading and writing from the mempak in a way compatible with official games.


Function Documentation

static uint16_t __calc_address_crc ( uint16_t  address) [static]

Calculate the 5 bit CRC on a mempak address.

This function, given an address intended for a mempak read or write, will calculate the CRC on the address, returning the corrected address | CRC.

Parameters:
[in]addressThe mempak address to calculate CRC over
Returns:
The mempak address | CRC
static uint8_t __calc_data_crc ( uint8_t *  data) [static]

Calculate the 8 bit CRC over a 32-byte block of data.

This function calculates the 8 bit CRC appropriate for checking a 32-byte block of data intended for or retrieved from a mempak.

Parameters:
[in]dataPointer to 32 bytes of data to run the CRC over
Returns:
The calculated 8 bit CRC over the data
static void __controller_exec_PIF ( void *  inblock,
void *  outblock 
) [static]

Send a block of data to the PIF and fetch the result.

Parameters:
[in]inblockThe formatted block to send to the PIF
[out]outblockThe buffer to place the output from the PIF
static void __get_accessories_present ( struct controller_data output) [static]

Query the PIF as to the status of accessories.

Parameters:
[out]outputStructure to place the result of the accessory query
static int __is_valid_accessory ( uint32_t  data) [static]

Return whether the given accessory is recognized.

Parameters:
[in]dataData as returned from PIF for a given controller
Returns:
Nonzero if valid accessory, zero otherwise
void controller_read ( struct controller_data output)

Read the controller button status for all controllers.

Read the controller button status immediately and return results to data. If calling this function, one should not also call controller_scan as this does not update the internal state of controllers.

Parameters:
[out]outputStructure to place the returned controller button status
void controller_scan ( )

Scan the controllers to determine the current button state.

Scan the four controller ports and calculate the buttons state. This must be called before calling get_keys_down, get_keys_up, get_keys_held, get_keys_pressed or get_dpad_direction.

int eeprom_present ( )

Probe the EEPROM interface.

Prove the EEPROM to see if it exists on this cartridge.

Returns:
Nonzero if EEPROM present, zero if EEPROM not present
void eeprom_read ( int  block,
uint8_t *const  buf 
)

Read a block from EEPROM.

Parameters:
[in]blockBlock to read data from. The N64 accesses eeprom in 8 byte blocks.
[out]bufBuffer to place the eight bytes read from EEPROM.
void eeprom_write ( int  block,
const uint8_t *const  data 
)

Write a block to EEPROM.

Parameters:
[in]blockBlock to write data to. The N64 accesses eeprom in 8 byte blocks.
[in]dataEight bytes of data to write to block specified
void execute_raw_command ( int  controller,
int  command,
int  bytesout,
int  bytesin,
unsigned char *  out,
unsigned char *  in 
)

Execute a raw PIF command.

Send an arbitrary command to a controller and receive arbitrary data back

Parameters:
[in]controllerThe controller (0-3) to send the command to
[in]commandThe command byte to send
[in]bytesoutThe number of parameter bytes the command requires
[in]bytesinThe number of result bytes expected
[in]outThe parameter bytes to send with the command
[out]inThe result bytes returned by the operation

Return a bitmask specifying which controllers have recognized accessories.

Queries the controller interface and returns a bitmask specifying which controllers have recognized accessories present. See CONTROLLER_1_INSERTED, CONTROLLER_2_INSERTED, CONTROLLER_3_INSERTED and CONTROLLER_4_INSERTED.

Returns:
A bitmask representing accessories recognized

Return a bitmask representing which controllers are present.

Queries the controller interface and returns a bitmask specifying which controllers are present. See CONTROLLER_1_INSERTED, CONTROLLER_2_INSERTED, CONTROLLER_3_INSERTED and CONTROLLER_4_INSERTED.

Returns:
A bitmask representing controllers present
int get_dpad_direction ( int  controller)

Return the DPAD calculated direction.

Return the direction of the DPAD specified in controller. Follows standard polar coordinates, where 0 = 0, pi/4 = 1, pi/2 = 2, etc... Returns -1 when not pressed. Must be used in conjunction with controller_scan

Parameters:
[in]controllerThe controller (0-3) to inspect
Returns:
A value 0-7 to represent which direction is held, or -1 when not pressed
struct controller_data get_keys_down ( ) [read]

Get keys that were pressed since the last inspection.

Return keys pressed since last detection. This returns a standard controller_data struct identical to controller_read. However, buttons are only set if they were pressed down since the last controller_scan.

Returns:
A structure representing which buttons were just pressed down
struct controller_data get_keys_held ( ) [read]

Get keys that were held since the last inspection.

Return keys held since last detection. This returns a standard controller_data struct identical to controller_read. However, buttons are only set if they were held since the last controller_scan.

Returns:
A structure representing which buttons were held
struct controller_data get_keys_pressed ( ) [read]

Get keys that are currently pressed, regardless of previous state.

This function works identically to controller_read except for it is safe to call when using controller_scan.

Returns:
A structure representing which buttons were pressed
struct controller_data get_keys_up ( ) [read]

Get keys that were released since the last inspection.

Return keys released since last detection. This returns a standard controller_data struct identical to controller_read. However, buttons are only set if they were released since the last controller_scan.

Returns:
A structure representing which buttons were just released
int identify_accessory ( int  controller)

Identify the accessory connected to a controller.

Given a controller, identify the particular accessory type inserted.

Parameters:
[in]controllerThe controller (0-3) to identify accessories on
Return values:
ACCESSORY_RUMBLEPAKThe accessory connected is a rumblepak
ACCESSORY_MEMPAKThe accessory connected is a mempak
ACCESSORY_VRUThe accessory connected is a VRU
ACCESSORY_NONEThe accessory was not recognized
int identify_controller ( int  controller)

Identify the controller connected to a controller port.

Given a controller port, identify the particular controller.

Parameters:
[in]controllerThe controller port (0-3) to identify controller on
Return values:
CONTROLLER_PADThe controller connected is a standard pad
CONTROLLER_MOUSEThe controller connected is a mouse
CONTROLLER_KEYBOARDThe controller connected is a keyboard
CONTROLLER_NONEThe controller port has no controller connected
int read_mempak_address ( int  controller,
uint16_t  address,
uint8_t *  data 
)

Read a chunk of data from a mempak.

Given a controller and an address, read 32 bytes from a mempak and return them in data.

Parameters:
[in]controllerWhich controller to read the data from (0-3)
[in]addressA 32 byte aligned offset to read from on the mempak
[out]dataBuffer to place 32 bytes of data read from the mempak
Return values:
0if reading was successful
-1if the controller was out of range
-2if there was no mempak present in the controller
-3if the mempak returned invalid data
void rumble_start ( int  controller)

Turn rumble on for a particular controller.

Parameters:
[in]controllerThe controller (0-3) who's rumblepak should activate
void rumble_stop ( int  controller)

Turn rumble off for a particular controller.

Parameters:
[in]controllerThe controller (0-3) who's rumblepak should deactivate
int write_mempak_address ( int  controller,
uint16_t  address,
uint8_t *  data 
)

Write a chunk of data to a mempak.

Given a controller and an address, write 32 bytes to a mempak from data.

Parameters:
[in]controllerWhich controller to write the data to (0-3)
[in]addressA 32 byte aligned offset to write to on the mempak
[out]dataBuffer to source 32 bytes of data to write to the mempak
Return values:
0if writing was successful
-1if the controller was out of range
-2if there was no mempak present in the controller
-3if the mempak returned invalid data
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines