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 | |
#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 | |
| |
#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 | |
| |
#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. |
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.
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.
[in] | address | The mempak address to calculate CRC over |
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.
[in] | data | Pointer to 32 bytes of data to run the CRC over |
static void __controller_exec_PIF | ( | void * | inblock, |
void * | outblock | ||
) | [static] |
Send a block of data to the PIF and fetch the result.
[in] | inblock | The formatted block to send to the PIF |
[out] | outblock | The 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.
[out] | output | Structure to place the result of the accessory query |
static int __is_valid_accessory | ( | uint32_t | data | ) | [static] |
Return whether the given accessory is recognized.
[in] | data | Data as returned from PIF for a given controller |
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.
[out] | output | Structure 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.
void eeprom_read | ( | int | block, |
uint8_t *const | buf | ||
) |
Read a block from EEPROM.
[in] | block | Block to read data from. The N64 accesses eeprom in 8 byte blocks. |
[out] | buf | Buffer to place the eight bytes read from EEPROM. |
void eeprom_write | ( | int | block, |
const uint8_t *const | data | ||
) |
Write a block to EEPROM.
[in] | block | Block to write data to. The N64 accesses eeprom in 8 byte blocks. |
[in] | data | Eight 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
[in] | controller | The controller (0-3) to send the command to |
[in] | command | The command byte to send |
[in] | bytesout | The number of parameter bytes the command requires |
[in] | bytesin | The number of result bytes expected |
[in] | out | The parameter bytes to send with the command |
[out] | in | The result bytes returned by the operation |
int get_accessories_present | ( | ) |
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.
int get_controllers_present | ( | ) |
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.
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
[in] | controller | The controller (0-3) to inspect |
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.
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.
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.
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.
int identify_accessory | ( | int | controller | ) |
Identify the accessory connected to a controller.
Given a controller, identify the particular accessory type inserted.
[in] | controller | The controller (0-3) to identify accessories on |
ACCESSORY_RUMBLEPAK | The accessory connected is a rumblepak |
ACCESSORY_MEMPAK | The accessory connected is a mempak |
ACCESSORY_VRU | The accessory connected is a VRU |
ACCESSORY_NONE | The 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.
[in] | controller | The controller port (0-3) to identify controller on |
CONTROLLER_PAD | The controller connected is a standard pad |
CONTROLLER_MOUSE | The controller connected is a mouse |
CONTROLLER_KEYBOARD | The controller connected is a keyboard |
CONTROLLER_NONE | The 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.
[in] | controller | Which controller to read the data from (0-3) |
[in] | address | A 32 byte aligned offset to read from on the mempak |
[out] | data | Buffer to place 32 bytes of data read from the mempak |
0 | if reading was successful |
-1 | if the controller was out of range |
-2 | if there was no mempak present in the controller |
-3 | if the mempak returned invalid data |
void rumble_start | ( | int | controller | ) |
Turn rumble on for a particular controller.
[in] | controller | The controller (0-3) who's rumblepak should activate |
void rumble_stop | ( | int | controller | ) |
Turn rumble off for a particular controller.
[in] | controller | The 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.
[in] | controller | Which controller to write the data to (0-3) |
[in] | address | A 32 byte aligned offset to write to on the mempak |
[out] | data | Buffer to source 32 bytes of data to write to the mempak |
0 | if writing was successful |
-1 | if the controller was out of range |
-2 | if there was no mempak present in the controller |
-3 | if the mempak returned invalid data |