libjoybus
Joybus implementation for 32-bit MCUs
Loading...
Searching...
No Matches
bus.h
1
6
7#pragma once
8
9#include <stddef.h>
10#include <stdint.h>
11
12#include <joybus/target.h>
13
14struct joybus;
15
17#define JOYBUS_FREQ_NOMINAL 250000
18
20#define JOYBUS_FREQ_N64_CONSOLE 244141 // PIF-NUS @ 15.625MHz / 64
21
23#define JOYBUS_FREQ_N64_EXTJOY JOYBUS_FREQ_N64_CONSOLE // SECCLK @ 1.953125MHz / 8
24
26#define JOYBUS_FREQ_N64_CONTROLLER 250000 // CNT-NUS @ 2MHz / 8
27
29#define JOYBUS_FREQ_N64_VRU 250000 // VCI-NUS @ 4MHz / 16
30
32#define JOYBUS_FREQ_GCN_CONSOLE 202500 // Flipper @ 162MHz / 800
33
35#define JOYBUS_FREQ_GCN_CONTROLLER 250000 // CNT-DOL @ 4MHz / 16
36
38#define JOYBUS_FREQ_WAVEBIRD_RECEIVER 225000 // WCRX-DOL @ 28.8MHz / 128
39
41#define JOYBUS_FREQ_WII_CONSOLE 202500 // Hollywood @ 243MHz / 1200
42
44#define JOYBUS_FREQ_GCN_GBA_CABLE 262144 // CPU-AGB @ 16.777216MHz / 64
45
47#define JOYBUS_INTER_TRANSFER_DELAY_US 80
48
50#define JOYBUS_REPLY_TIMEOUT_US 64
51
53#define JOYBUS_BUS_IDLE_US 100
54
56#define JOYBUS_BLOCK_SIZE 64
57
61#define JOYBUS(bus) ((struct joybus *)(bus))
62
73
85typedef void (*joybus_transfer_cb)(struct joybus *bus, int status, void *user_data);
86
87// API for a Joybus backend - internal use only
88struct joybus_api {
89 int (*enable)(struct joybus *bus);
90 int (*disable)(struct joybus *bus);
91 int (*transfer)(struct joybus *bus, const uint8_t *write_buf, uint8_t write_len, uint8_t *read_buf, uint8_t read_len,
92 joybus_transfer_cb callback, void *user_data);
93};
94
96 joybus_transfer_cb callback;
97 void *user_data;
98 uint8_t *response;
99 uint8_t arg;
100};
101
105struct joybus {
107 const struct joybus_api *api;
108
111
113 uint32_t freq;
114
117
120
121 uint8_t command_buffer[JOYBUS_BLOCK_SIZE];
122 uint8_t response_buffer[JOYBUS_BLOCK_SIZE];
123 struct joybus_host_op host_op;
124};
125
136static inline int joybus_enable(struct joybus *bus, enum joybus_mode mode)
137{
138 bus->mode = mode;
139 return bus->api->enable(bus);
140}
141
147static inline int joybus_disable(struct joybus *bus)
148{
149 return bus->api->disable(bus);
150}
151
168static inline int joybus_transfer(struct joybus *bus, const uint8_t *write_buf, uint8_t write_len, uint8_t *read_buf,
169 uint8_t read_len, joybus_transfer_cb callback, void *user_data)
170{
171 return bus->api->transfer(bus, write_buf, write_len, read_buf, read_len, callback, user_data);
172}
173
189int joybus_transfer_sync(struct joybus *bus, const uint8_t *write_buf, uint8_t write_len, uint8_t *read_buf,
190 uint8_t read_len);
191
204int joybus_attach_target(struct joybus *bus, struct joybus_target *target);
205
213int joybus_detach_target(struct joybus *bus, struct joybus_target *target);
214
231static inline int joybus_byte_received(struct joybus *bus, const uint8_t *command, uint8_t byte_idx,
232 joybus_target_response_cb send_response, void *user_data)
233{
234 // Later bytes go straight to the target that claimed the command
235 if (byte_idx > 1)
236 return joybus_target_byte_received(bus->active_target, command, byte_idx, send_response, user_data);
237
238 // Offer the first byte to each target in attachment order until one claims the command
239 for (struct joybus_target *target = bus->targets; target; target = target->next) {
240 int rc = joybus_target_byte_received(target, command, byte_idx, send_response, user_data);
241 if (rc == -JOYBUS_ERR_NOT_SUPPORTED)
242 continue;
243
244 bus->active_target = target;
245 return rc;
246 }
247
248 // No target claimed the command
249 bus->active_target = NULL;
251}
252
253// Context for a blocking Joybus operation
255 volatile bool done;
256 volatile int status;
257};
258
259// Transfer completion callback that records the status into a joybus_sync_ctx.
260void joybus_sync_cb(struct joybus *bus, int status, void *user_data);
261
262// Busy-wait on a joybus_sync_ctx until the operation completes
263int joybus_sync(int start_status, struct joybus_sync_ctx *ctx);
264
static int joybus_target_byte_received(struct joybus_target *target, const uint8_t *command, uint8_t byte_idx, joybus_target_response_cb send_response, void *user_data)
Handle a received command byte for a single Joybus target.
Definition target.h:116
void(* joybus_target_response_cb)(const uint8_t *response, uint8_t len, void *user_data)
Callback type for sending responses from target command handlers.
Definition target.h:68
joybus_mode
The role a Joybus instance plays on the bus.
Definition bus.h:66
void(* joybus_transfer_cb)(struct joybus *bus, int status, void *user_data)
Function type for transfer completion callbacks.
Definition bus.h:85
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.
Definition bus.h:231
static int joybus_enable(struct joybus *bus, enum joybus_mode mode)
Enable the Joybus instance in the given mode.
Definition bus.h:136
#define JOYBUS_BLOCK_SIZE
Maximum size of a Joybus transfer, in bytes.
Definition bus.h:56
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.
Definition bus.c:61
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.
Definition bus.h:168
static int joybus_disable(struct joybus *bus)
Disable the Joybus instance.
Definition bus.h:147
int joybus_attach_target(struct joybus *bus, struct joybus_target *target)
Attach a target to handle commands received in target mode.
Definition bus.c:3
int joybus_detach_target(struct joybus *bus, struct joybus_target *target)
Detach a target from the bus.
Definition bus.c:20
@ JOYBUS_MODE_HOST
Host mode, sends commands and reads responses from a target device.
Definition bus.h:68
@ JOYBUS_MODE_TARGET
Target mode, listens for commands from a host device and responds accordingly.
Definition bus.h:71
@ JOYBUS_ERR_NOT_SUPPORTED
Command not supported by Joybus target.
Definition errors.h:27
uint8_t status
Status flags.
Definition identify.h:4
Definition bus.h:88
Definition bus.h:95
Definition bus.h:254
Interface for a Joybus target, a device on the Joybus which responds to commands from a host.
Definition target.h:92
struct joybus_target * next
The next target attached to the same bus, in attachment order.
Definition target.h:100
A Joybus instance.
Definition bus.h:105
enum joybus_mode mode
The operating mode of this Joybus instance (host or target).
Definition bus.h:110
uint32_t freq
The frequency of the bus, in Hz.
Definition bus.h:113
const struct joybus_api * api
The backend API implementation for this Joybus instance.
Definition bus.h:107
struct joybus_target * targets
The targets attached to this Joybus instance, in attachment order.
Definition bus.h:116
struct joybus_target * active_target
The target that claimed the command being received, if any.
Definition bus.h:119