libjoybus
Joybus implementation for 32-bit MCUs
Loading...
Searching...
No Matches
Joybus

Joybus library core functionality. More...

Data Structures

struct  joybus_api
struct  joybus_host_op
struct  joybus
 A Joybus instance. More...
struct  joybus_sync_ctx

Macros

#define JOYBUS_USE_RAM_FUNCS   1
 Whether to place latency-critical functions in RAM.
#define JOYBUS_RAM_FUNC
 Attributes for a latency-critical function, such as a target command handler.
#define JOYBUS_RAM_DATA
#define JOYBUS_FREQ_NOMINAL   250000
 Nominal Joybus frequency, matching an OEM N64/GameCube controller.
#define JOYBUS_FREQ_N64_CONSOLE   244141
 Joybus frequency of an N64 console (NUS-001).
#define JOYBUS_FREQ_N64_EXTJOY   JOYBUS_FREQ_N64_CONSOLE
 Joybus frequency of an external joybus device (EEPROM/RTC on an N64 cartridge).
#define JOYBUS_FREQ_N64_CONTROLLER   250000
 Joybus frequency of an N64 controller (NUS-005).
#define JOYBUS_FREQ_N64_VRU   250000
 Joybus frequency of an N64 VRU (NUS-020).
#define JOYBUS_FREQ_GCN_CONSOLE   202500
 Joybus frequency of a GameCube console (DOL-001 / DOL-101).
#define JOYBUS_FREQ_GCN_CONTROLLER   250000
 Joybus frequency of a GameCube controller (DOL-003).
#define JOYBUS_FREQ_WAVEBIRD_RECEIVER   225000
 Joybus frequency of WaveBird receiver (DOL-005)
#define JOYBUS_FREQ_WII_CONSOLE   202500
 Joybus frequency of a Wii console (RVL-001 / RVL-101 / RVL-201).
#define JOYBUS_FREQ_GCN_GBA_CABLE   262144
 Joybus frequency of a GameCube Game Boy Advance cable (DOL-011).
#define JOYBUS_INTER_TRANSFER_DELAY_US   80
 Minimum delay between Joybus transfers, in microseconds.
#define JOYBUS_REPLY_TIMEOUT_US   64
 Timeout for waiting for a reply from a target, in microseconds.
#define JOYBUS_BUS_IDLE_US   100
 Minimum line-high time to consider the bus idle, in microseconds.
#define JOYBUS_BLOCK_SIZE   64
 Maximum size of a Joybus transfer, in bytes.
#define JOYBUS(bus)
 Macro to cast a backend-specific Joybus instance to a generic Joybus instance.
#define JOYBUS_N64_PAK_FS_PAGE_SIZE   256
 Size of one page in bytes, the unit the filesystem allocates in.
#define JOYBUS_N64_PAK_FS_MAX_BANKS   62
 The most banks whose system area fits in the first bank.
#define JOYBUS_N64_PAK_FS_SYSTEM_PAGES(banks)
 Number of system pages in the first bank for a given bank count.

Typedefs

typedef void(* joybus_transfer_cb) (struct joybus *bus, int status, void *user_data)
 Function type for transfer completion callbacks.

Enumerations

enum  joybus_mode {
  JOYBUS_MODE_HOST ,
  JOYBUS_MODE_TARGET
}
 The role a Joybus instance plays on the bus. More...
enum  joybus_error {
  JOYBUS_ERR_DISABLED = 1 ,
  JOYBUS_ERR_BUSY ,
  JOYBUS_ERR_TIMEOUT ,
  JOYBUS_ERR_NOT_SUPPORTED ,
  JOYBUS_ERR_CHECKSUM ,
  JOYBUS_ERR_NO_DEVICE ,
  JOYBUS_ERR_INVALID_ARG
}
 Joybus error codes. More...

Functions

static int joybus_enable (struct joybus *bus, enum joybus_mode mode)
 Enable the Joybus instance in the given mode.
static int joybus_disable (struct joybus *bus)
 Disable the Joybus instance.
static int joybus_transfer (struct joybus *bus, const uint8_t *write_buf, uint8_t write_len, uint8_t *read_buf, uint8_t read_len, joybus_transfer_cb callback, void *user_data)
 Perform a Joybus "write then read" transfer.
int joybus_transfer_sync (struct joybus *bus, const uint8_t *write_buf, uint8_t write_len, uint8_t *read_buf, uint8_t read_len)
 Perform a synchronous "write then read" Joybus transfer.
int joybus_attach_target (struct joybus *bus, struct joybus_target *target)
 Attach a target to handle commands received in target mode.
int joybus_detach_target (struct joybus *bus, struct joybus_target *target)
 Detach a target from the bus.
static int joybus_byte_received (struct joybus *bus, const uint8_t *command, uint8_t byte_idx, joybus_target_response_cb send_response, void *user_data)
 Offer a received command byte to the targets attached to the bus.
void joybus_sync_cb (struct joybus *bus, int status, void *user_data)
int joybus_sync (int start_status, struct joybus_sync_ctx *ctx)
uint8_t joybus_data_checksum_update (uint8_t crc, uint8_t byte)
 Fold one byte into a running Joybus data checksum.
uint8_t joybus_data_checksum (const uint8_t *data, size_t size)
 Compute the CRC-8 checksum of a Joybus data buffer.
uint8_t joybus_address_checksum (uint16_t addr)
 Compute the CRC-5 address checksum for data transfer commands.
bool joybus_n64_pak_fs_is_id_block (uint16_t addr)
 Check whether a block address in the first bank holds a copy of the ID.
uint8_t joybus_n64_pak_fs_id_banks (const uint8_t block[JOYBUS_N64_PAK_BLOCK_SIZE])
 Read the bank count an ID block names.
bool joybus_n64_pak_fs_valid (const uint8_t *bank0, uint8_t banks)
 Check whether a bank holds a filesystem for the given bank count.
int joybus_n64_pak_fs_format (uint8_t *bank0, uint8_t banks, uint32_t random)
 Write a fresh filesystem for the given bank count into a bank.

Detailed Description

Joybus library core functionality.

Checksum routines used by various Joybus data transfer commands.

N64 Controller Pak filesystem helpers.

A Controller Pak keeps its system area in the first bank: four copies of an ID block in page 0, an inode table and a mirror of it per bank, then two pages of note table. These routines write that area for a given bank count and check whether one is present, so an emulated pak can present itself as formatted. They work on a bank held in memory and do not touch the bus.

Macro Definition Documentation

◆ JOYBUS

#define JOYBUS ( bus)
Value:
((struct joybus *)(bus))
A Joybus instance.
Definition bus.h:105

Macro to cast a backend-specific Joybus instance to a generic Joybus instance.

◆ JOYBUS_N64_PAK_FS_SYSTEM_PAGES

#define JOYBUS_N64_PAK_FS_SYSTEM_PAGES ( banks)
Value:
(3 + 2 * (banks))

Number of system pages in the first bank for a given bank count.

◆ JOYBUS_RAM_FUNC

#define JOYBUS_RAM_FUNC

Attributes for a latency-critical function, such as a target command handler.

Places it in RAM instead of executing it in place from flash, so a flash fetch or cache miss cannot add latency to the response. A no-op when JOYBUS_USE_RAM_FUNCS is 0, or on platforms that are not yet wired up.

◆ JOYBUS_USE_RAM_FUNCS

#define JOYBUS_USE_RAM_FUNCS   1

Whether to place latency-critical functions in RAM.

Enabled by default, for a deterministic command-to-response turnaround. Define as 0 to keep them in flash, saving RAM at the cost of a variable turnaround (a flash fetch or cache miss can slow a reply).

Typedef Documentation

◆ joybus_transfer_cb

typedef void(* joybus_transfer_cb) (struct joybus *bus, int status, void *user_data)

Function type for transfer completion callbacks.

Invoked once, after the async call has returned, when a started transfer completes. Runs in transfer-completion context, which is an interrupt on most backends, so it must not block.

Parameters
busthe Joybus associated with the transfer
status0 on success, a negative joybus_error on failure
user_datathe user_data passed to the async function

Enumeration Type Documentation

◆ joybus_error

Joybus error codes.

Errors are reported as negatives of these codes. Functions return 0 on success or a negative joybus_error on failure, and the status passed to a transfer callback uses the same convention. If an async function returns an error, the transfer did not start, so its callback is not invoked.

Enumerator
JOYBUS_ERR_DISABLED 

Bus not enabled.

JOYBUS_ERR_BUSY 

Bus is busy with another operation.

JOYBUS_ERR_TIMEOUT 

Transfer timed out.

JOYBUS_ERR_NOT_SUPPORTED 

Command not supported by Joybus target.

JOYBUS_ERR_CHECKSUM 

Checksum error.

JOYBUS_ERR_NO_DEVICE 

Expected device not detected.

JOYBUS_ERR_INVALID_ARG 

Invalid argument.

◆ joybus_mode

The role a Joybus instance plays on the bus.

Enumerator
JOYBUS_MODE_HOST 

Host mode, sends commands and reads responses from a target device.

JOYBUS_MODE_TARGET 

Target mode, listens for commands from a host device and responds accordingly.

Function Documentation

◆ joybus_address_checksum()

uint8_t joybus_address_checksum ( uint16_t addr)

Compute the CRC-5 address checksum for data transfer commands.

Parameters
addran 11 bit address to checksum
Returns
CRC-5 checksum of the address

◆ joybus_attach_target()

int joybus_attach_target ( struct joybus * bus,
struct joybus_target * target )

Attach a target to handle commands received in target mode.

A bus accepts more than one target. Each command is offered to the attached targets in attachment order, so a target attached earlier takes priority over those attached after it. Attaching a target that is already attached has no effect.

Parameters
busthe Joybus instance to use
targetthe target to attach
Returns
0 on success, a negative joybus_error on failure

◆ joybus_byte_received()

int joybus_byte_received ( struct joybus * bus,
const uint8_t * command,
uint8_t byte_idx,
joybus_target_response_cb send_response,
void * user_data )
inlinestatic

Offer a received command byte to the targets attached to the bus.

Called by backends in target mode as each command byte arrives. The first byte of a command is offered to each attached target in attachment order until one claims it by returning anything other than -JOYBUS_ERR_NOT_SUPPORTED. Every later byte of the command goes to that target alone.

Parameters
busthe Joybus instance that received the byte
commandthe command buffer
byte_idxthe index of the byte that was just received
send_responsea callback function to send the response
user_datauser data to pass to the response callback
Returns
positive number of bytes still expected, 0 if no more bytes expected, a negative joybus_error on failure. -JOYBUS_ERR_NOT_SUPPORTED if no target claimed the command

◆ joybus_data_checksum()

uint8_t joybus_data_checksum ( const uint8_t * data,
size_t size )

Compute the CRC-8 checksum of a Joybus data buffer.

Parameters
databuffer to checksum
sizenumber of bytes in data
Returns
the CRC-8 checksum of the buffer

◆ joybus_data_checksum_update()

uint8_t joybus_data_checksum_update ( uint8_t crc,
uint8_t byte )

Fold one byte into a running Joybus data checksum.

Seed crc with 0 on the first call and pass the result back in on subsequent calls to compute the checksum over a stream of bytes.

Parameters
crcrunning checksum value, or 0 to start a fresh checksum
bytenext byte to fold in
Returns
updated running checksum after folding in byte

◆ joybus_detach_target()

int joybus_detach_target ( struct joybus * bus,
struct joybus_target * target )

Detach a target from the bus.

Parameters
busthe Joybus instance to use
targetthe target to detach
Returns
0 on success, a negative joybus_error on failure

◆ joybus_disable()

int joybus_disable ( struct joybus * bus)
inlinestatic

Disable the Joybus instance.

Parameters
busthe Joybus instance to disable

◆ joybus_enable()

int joybus_enable ( struct joybus * bus,
enum joybus_mode mode )
inlinestatic

Enable the Joybus instance in the given mode.

Spins up the backend peripherals and starts operating as a host or a target. The mode applies until the instance is disabled; to switch modes, disable the instance and enable it again with the other mode.

Parameters
busthe Joybus instance to enable
modewhether to operate as a host or a target

◆ joybus_n64_pak_fs_format()

int joybus_n64_pak_fs_format ( uint8_t * bank0,
uint8_t banks,
uint32_t random )

Write a fresh filesystem for the given bank count into a bank.

Only the system area is written. The data pages keep their contents but are all marked free, so a console sees an empty pak.

Parameters
bank0the first bank of the pak, JOYBUS_N64_PAK_BANK_SIZE bytes
bankshow many banks the pak presents, 1 to JOYBUS_N64_PAK_FS_MAX_BANKS
randomvalue stored in the ID to tell this pak apart from others
Returns
positive number of bytes written from the start of the bank, a negative joybus_error on failure

◆ joybus_n64_pak_fs_id_banks()

uint8_t joybus_n64_pak_fs_id_banks ( const uint8_t block[JOYBUS_N64_PAK_BLOCK_SIZE])

Read the bank count an ID block names.

Parameters
blockan ID block, JOYBUS_N64_PAK_BLOCK_SIZE bytes
Returns
the bank count in the block

◆ joybus_n64_pak_fs_is_id_block()

bool joybus_n64_pak_fs_is_id_block ( uint16_t addr)

Check whether a block address in the first bank holds a copy of the ID.

Parameters
addrblock-aligned address within the first bank
Returns
true if the block is one of the four ID copies, false otherwise

◆ joybus_n64_pak_fs_valid()

bool joybus_n64_pak_fs_valid ( const uint8_t * bank0,
uint8_t banks )

Check whether a bank holds a filesystem for the given bank count.

Parameters
bank0the first bank of the pak, JOYBUS_N64_PAK_BANK_SIZE bytes
bankshow many banks the pak presents
Returns
true if an intact ID names that many banks, false otherwise

◆ joybus_transfer()

int joybus_transfer ( struct joybus * bus,
const uint8_t * write_buf,
uint8_t write_len,
uint8_t * read_buf,
uint8_t read_len,
joybus_transfer_cb callback,
void * user_data )
inlinestatic

Perform a Joybus "write then read" transfer.

Sends a command to a device and reads the response. Returns once the transfer has started, and callback is invoked with the status when it completes. The provided buffers must stay valid until the callback runs.

Parameters
busthe Joybus instance to use
write_bufthe buffer containing the command to send
write_lenthe number of bytes to write
read_bufthe buffer to store the response in
read_lenthe number of bytes to read
callbackinvoked once when the transfer completes
user_datauser data to pass to the callback
Returns
0 if the transfer was started, a negative joybus_error otherwise

◆ joybus_transfer_sync()

int joybus_transfer_sync ( struct joybus * bus,
const uint8_t * write_buf,
uint8_t write_len,
uint8_t * read_buf,
uint8_t read_len )

Perform a synchronous "write then read" Joybus transfer.

Sends a command to a device and blocks until the response arrives.

Parameters
busthe Joybus instance to use
write_bufthe buffer containing the command to send
write_lenthe number of bytes to write
read_bufthe buffer to store the response in
read_lenthe number of bytes to read
Returns
0 on success, a negative joybus_error on failure
Warning
Blocks by busy-waiting, so it must not be called from an interrupt or timer callback. Use joybus_transfer() there.