set up general pages, complete config guide and background info

This commit is contained in:
Naxdy 2024-04-08 00:09:45 +02:00
parent da9cdd2b47
commit 47eb6f2371
Signed by: Naxdy
GPG key ID: CC15075846BCE91B
16 changed files with 460 additions and 2 deletions

3
.gitignore vendored
View file

@ -1,2 +1,3 @@
/result
/.direnv
/.direnv
/book

9
book.toml Normal file
View file

@ -0,0 +1,9 @@
[book]
authors = ["Naxdy"]
language = "en"
multilingual = false
src = "src"
title = "NaxGCC Documentation"
[preprocessor.katex]
after = ["links"]

View file

@ -16,7 +16,7 @@
{
devShells.default = pkgs.mkShell {
nativeBuildInputs = builtins.attrValues {
inherit (pkgs) mdbook;
inherit (pkgs) mdbook mdbook-katex;
};
};
});

17
src/SUMMARY.md Normal file
View file

@ -0,0 +1,17 @@
# Summary
[Introduction](./introduction.md)
[On Polling and Input Consistency](./input-consistency.md)
# User Guide
- [NaxGCC Buying Guide](./buying-guide.md)
- [Configuring Your Controller](./configuration.md)
- [Updating Controller Firmware](./update-firmware.md)
# Maker Guide
- [JLCPCB Parts Ordering](./jlcpcb-parts-ordering.md)
- [Hardware Assembly](./assembly.md)
- [Phob2.0 -> NaxGCC Conversion](./phob2-to-naxgcc.md)

1
src/assembly.md Normal file
View file

@ -0,0 +1 @@
# Assembly Guide

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
src/assets/oscilloscope.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

BIN
src/assets/smashscope.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

1
src/buying-guide.md Normal file
View file

@ -0,0 +1 @@
# NaxGCC Buying Guide

289
src/configuration.md Normal file
View file

@ -0,0 +1,289 @@
# Configuring Your Controller
This page contains all the information needed for configuring & calibrating your controller. Click on any of the links below to quickly navigate to a given section.
1. [Initial Calibration](#initial-calibration)
2. [Configuration Options](#configuration-options)
- [Stick Calibration](#stick-calibration)
- [Smart Snapback Adjustment](#smart-snapback-adjustment)
- [Waveshaping Adjustment](#waveshaping-adjustment)
- [Stick Scaling Adjustment](#stick-scaling-adjustment)
- [Cardinal Snapping Adjustment](#cardinal-snapping-adjustment)
- [Axis Smoothing Adjustment](#axis-smoothing-adjustment)
- [Input Consistency Mode Toggle](#input-consistency-mode-toggle)
- [Display Values](#display-values)
# Initial Calibration
The calibration process for the NaxGCC is very similar to that of the PhobGCC, but it is not the same. Furthermore, changes may be introduced in the future that further cause the processes to diverge, so it is best to refer to this document as your source of information, as opposed to the PhobGCC's docs.
### Before You Start
When first plugging in your controller after flashing the NaxGCC firmware, you will notice that your sticks don't work at all (even if you flashed the firmware onto a previously-calibrated Phob 2.0 board).
Don't worry, this is perfectly normal and expected, as the sticks first need to be calibrated to your specific magnet / magnet-mount combination, as well as the layout of your controller shell.
Calibration is not very complicated and usually only takes a few minutes to complete. To start, you will need:
- your NaxGCC
- a computer with the [Dolphin](https://dolphin-emu.org/) emulator installed
- a copy of [Smashscope](https://goomwave.com/2020/06/28/smashscope-guide/)
- a USB-C to USB-A cable in order to connect your controller to your PC
### Getting Started
Before loading up Smashscope, ensure Dolphin's controller settings look like in the image below. **Especially important is that you do not emulate any Wii remotes, as otherwise Smashscope will be unable to read your sticks!**
<img src="./assets/dolphinsettings.png" style="display: block; margin-left: auto; margin-right: auto;" />
Start by powering up Dolphin and booting into Smashscope. You should see a screen similar to this:
<img src="./assets/smashscope.png" style="display: block; margin-left: auto; margin-right: auto;" />
If you haven't already, connect your controller now. Then press `A` in order to enter the "Controller Test" mode. You should see an image similar to this:
<img src="./assets/controllertest.png" style="display: block; margin-left: auto; margin-right: auto;" />
If your sticks don't look like this, but are completely out of whack instead, again, don't worry, this is to be expected. This screen will display any inputs you make on your NaxGCC in real time. Additionally, pressing the Z button will cause your NaxGCC to rumble.
## Beginning Calibration
Now it's time to start calibrating your sticks. First, you will need to enter config mode by simultaneously pressing `A+X+Y+Start`. Your controller will freeze for one second while keeping the buttons held, and additionally pressing the triggers, before returning to its normal state. Now that you are in config mode, you have access to all calibration and configuration options.
Head on over to [Stick Calibration](#stick-calibration) and begin calibrating your control stick and your C stick. Once you've done so, it is highly recommended to determine whether your stick has any snapback (and how much), and configure the related snapback options in order to tone it down, or eliminate it entirely.
To do so, hold B to exit the "Controller Test" mode, and go into the "Oscilloscope" mode. In this mode, you can flick your stick left/right/up/down and see how far it extends into the opposite direction before returning back to center, giving you an easy-to-understand visualization of your stick's snapback. Your stick's X axis is displayed in red, and your stick's Y axis is blue.
For example, if you flick your stick to the left, ideally your `Min X` would be `-100` (or another number far in the negatives) and your `Max X` would be `0` or close to `0`. The more your `Max X` overshoots 0, the more snapback your stick has from left to right. The below screenshot shows a stick flick to the left with some snapback attached to it:
<img src="./assets/oscilloscope.png" style="display: block; margin-left: auto; margin-right: auto;" />
NaxGCC features a variety of snapback filtering options. Go ahead and give each one a try, you'll find that different options may have a bigger or smaller impact on your particular controller:
- [Waveshaping](#waveshaping-adjustment)
- [Axis Smoothing](#axis-smoothing-adjustment)
- [Smart Snapback](#smart-snapback-adjustment)
Adjust these in the "Controller Test" screen, then return to the oscilloscope to check the results.
Finally, after having tuned your snapback, you'll probably want to select your preferred [Input Consistency Mode](#input-consistency-mode-toggle).
# Configuration Options
These are all options you have while config mode is active. Config mode is activated by simultaneously pressing `A+X+Y+Start`.
---
## Stick Calibration
**Button Combo (Analog Stick):** `A+X+Y+L`
**Button Combo (C-Stick):** `A+X+Y+R`
- Stick calibration has two phases: measurement and notch adjustment.
- During the Measurement Phase, you have the controller record the physical location of the corners of the gate and any modder-added notches.
- During the Notch Adjustment Phase, you can tweak the output angles of the notches you measured.
- You **must** complete both measurement and notch adjustment for the setting to be saved.
### Measurement Phase
The first phase involves having the controller record the positions of the physical gate corners and notches as calibration reference points.
When in the measurement phase, the other stick's position (the one you're **not** currently calibrating) will alternate between the center and a position along the rim, starting with the cardinal directions. It shows you what you're supposed to do with the stick you're currently calibrating:
- If the other stick is centered, let go of the stick you're calibrating and press `A` to record that position.
- If the other stick is not centered, move the stick you're calibrating into that position, ensuring that it is perfectly located within the notch, and press `A` to measure that position.
**NOTE:** If you don't have a notch in the position the other stick indicates, simply let go of the stick you're calibrating and press `A` to advance. This notch will then be marked as "Inactive" by the firmware.
- You **must measure all four cardinal directions (East, North, West, South) and all four diagonal directions** or calibration will not work.
- The first time you calibrate a controller that has modder-added notches, it is highly recommended to skip all the modder added notches and start with only the 8 primary directions.
- Once you finish measuring all the notches (32 presses of `A`), the stick should behave normally. **You are not done calibrating.** Proceed to the [Notch Adjustment Phase below](#notch-adjustment-phase).
If it does not behave as expected, see Measurement Phase Troubleshooting below.
#### Measurement Phase Troubleshooting
- If the output of the stick you're calibrating is not accurate during this phase, do not worry. The previous calibration does not matter.
- If the other stick is not alternating between being centered and circling all the way around the rim, you need to unplug and replug, and then restart Dolphin.
- If after the measurement phase is done, the stick has one or two sectors that jump into another quadrant randomly, you probably mis-measured a notch. Mash `A` a bunch to finish the calibration and start again.
- If after the measurement phase is done, the stick output is completely haywire and jumping all over the place randomly, you may have let go of the stick before pressing `A`. Mash `A` a bunch to finish the calibration and start again.
- Alternatively, if you have Firefox notches, try calibrating the main 8 directions only to completion, then go back and calibrate all of them.
- If after the measurement phase is done, the stick output is backwards on one or both axes, you probably were trying to make the stick _output_ match the other stick, instead of moving the physical stick into the notch indicated by the other stick. Mash `A` a bunch to finish the calibration and start again.
- If after the measurement phase is done, your stick does not perfectly move between `-100` and `100`, but instead seems to be somewhat offset, you may need to ensure that the magnets you're using are positioned to have opposite polarity.
### Notch Adjustment Phase
After the measurements are complete, this phase lets you adjust exactly where the non-cardinal notches are mapped to. This is useful, for example, if you want to ensure that you're getting up/down tilts when in one of the top/bottom corners, instead of forward tilts.
When in the notch adjustment phase, the other stick will stay along the rim and rotate along from notch to notch, starting with the diagonals. This indicates which notch is currently adjusted.
- The position of the stick you're calibrating does not affect notch adjustment. The output is a **live preview** of how the calibration will be with your given adjustments, so feel free to move your stick around to see what it would be like.
- Press `X` or `Y` to shift the output of the notch clockwise or counterclockwise, respectively.
Note that you will only be able to actually observe the change when you're moving the stick to the notch that's currently being adjusted.
- To discard your current modifications and reset to the default notch state, press `B`.
- Press `A` to proceed to the next notch.
When the other stick's position returns to center, or resumes displaying the actual stick's position (which may be all over the place if it's not yet calibrated), the stick calibration is now saved.
#### Notch Adjustment Troubleshooting
- If your notch coordinates are very inconsistent, try twisting the stick like a knob and see if the origin value shifts. If so, try gently tightening the screws holding the stickbox down; they may be loose.
- If your notch coordinates have slightly different values when approaching straight from center compared to rolling clockwise or counterclockwise along the rim, this is normal (within two or three values).
- If your notch coordinates cannot be adjusted to the desired value, check the other stick's coordinates to see if it's too far from the desired value. You can try recalibrating from the start and measuring it again, but it may not help. See a modder to get your notches adjusted if needed.
---
## Smart Snapback Adjustment
**Button Combo (Analog Stick):** `A+X/Y+Du/Dd`
**Button Combo (C-Stick):** `A+Z+X/Y+Du/Dd`
> **NOTE:** This feature is currently unused for the C-Stick. While you can still adjust the values, changing them won't actually affect the stick's behavior.
Button combos for adjusting values for the C-Stick are the same as for the analog stick, with an added press of the `Z` button.
Increasing the stick Smart Snapback Filter adjustment doesnt hurt responsiveness of the stick when moving away from the center. Increasing the value of this filter only makes it return to center more slowly.
- Press `A+(Z)` for your stick, `X/Y` for your axis, and `D-pad up/down` to increase/decrease.
- Example: `A+(Z)+X+Du` suppresses X-axis snapback _more_, and `A+(Z)+Y-Dd` suppresses Y-axis snapback _less_.
- When you change this setting, the current snapback filter settings are shown as the numerical coordinates on the stick you're adjusting.
- The scale goes from `-10` to `+10`, and defaults to `4`.
- `0` completely disables the Smart Snapback Filter. This removes the rise time improvements, hurting dashdancing on the X axis, and you will have snapback.
- Positive values have strong rise time reduction that promotes fast tilt inputs into smash inputs.
Higher values have stronger snapback suppression.
- Negative values minimize rise time reduction and make the stick behave more like an OEM controller.
More negative values have stronger snapback suppression.
- Sticks usually need a setting of `4-7`. `9+` is for special situations such as metal stick caps or lighter spring weights.
- If you have an OEM stick cap and snapback is still a problem, try setting the snapback filter to `0` and check how far the snapback goes. If it goes past `70`, you may have to tame snapback by adding a bit of grease to the stickbox.
Press `Du+Start` while in config mode to display the smart snapback values on each stick.
---
## Waveshaping Adjustment
**Button Combo (Analog Stick):** `L+X/Y+Du/Dd`
**Button Combo (C-Stick):** `L+Z+X/Y+Du/Dd`
Button combos for adjusting values for the C-Stick are the same as for the analog stick, with an added press of the `Z` button.
The Waveshaping filter stops the output from moving while the stick axis is moving quickly. This setting controls the threshold where that transition occurs.
This can be used to make short flicks behave more like a good OEM controller. This enhancement to flicks works best with an OEM spring or a Smalley L2 spring, not with lighter "slickbox" style springs, but you can crank it up and make it work at the expense of responsiveness.
- Press `L+(Z)` for your stick, `X/Y` for your axis, and `D-pad up/down` to increase/decrease
- Example: `L+(Z)+X+Du` strengthens the effect on the X axis, and `L+(Z)+Y+Dd` reduces the effect on the Y axis.
- When you change this setting, the current Waveshaping filter settings are shown as the numerical coordinates on the stick you're adjusting.
- The scale goes from `0-15`, and defaults to `0`.
- `0` disables waveshaping entirely.
- Ideally, change both axes together.
Press `L+Start` while in config mode to display the waveshaping values on each stick.
---
## Stick Scaling Adjustment
**Button Combo (Analog Stick):** `L+A+Du/Dd`
**Button Combo (C-Stick):** `L+Z+A+Du/Dd`
> **NOTE:** This feature has simply been ported over from the PhobGCC for compatibility reasons, but is not very useful for Super Smash Bros. Ultimate. It is recommended to leave this setting at its default value of `100`.
Button combos for adjusting values for the C-Stick are the same as for the analog stick, with an added press of the `Z` button.
The Stick Scaling setting allows the user to adjust what value the stick can reach at the edge of the gate. Super Smash Bros. Melee has a unit circle that ranges from `-80` to `+80`, OEM Gamecube controllers range from roughly `-100` to `+100`, and the GCC protocol allows for `-128` to `+127`. The NaxGCC, just like the PhobGCC, hard limits its own stick outputs to a range from `-125` to `+125`, but this setting corresponds to what you get immediately after calibration.
- Press `L+A+(Z)` for your stick, and `D-pad up/down` to increase/decrease
- Example: `L+Z+A+Du` strengthens the effect on the C-Stick, and `L+A+Dd` reduces the effect on the control stick.
- When you change this setting, the current Stick Scaling filter settings are shown as the numerical coordinates on the stick you're adjusting.
- The scale goes from `82-125`, and defaults to `100`.
- This changes the physical distance to the rim of the Melee unit circle.
- At `82`, the rim of the Melee unit circle is basically at the rim of the controller, requiring larger motions for things like smash attacks.
- At `125`, the rim of the Melee unit circle is much farther in, requiring smaller motions for things like smash attacks.
---
## Cardinal Snapping Adjustment
**Button Combo (Analog Stick):** `R+A+Du/Dd`
**Button Combo (C-Stick):** `R+Z+A+Du/Dd`
> **NOTE:** This feature has simply been ported over from the PhobGCC for compatibility reasons, but is not very useful for Super Smash Bros. Ultimate. It is recommended to leave this setting at its default value of `6`.
Button combos for adjusting values for the C-Stick are the same as for the analog stick, with an added press of the `Z` button.
The Analog Stick Cardinal Snapping setting allows the user to adjust the width of the window around the cardinals around which the stick will snap to perfect `1.0`.
- Press `R+A+(Z)` for your stick, and `D-pad up/down` to increase/decrease
- Example: `R+Z+A+Du` strengthens the effect on the C-Stick, and `R+A+Dd` reduces the effect on the control stick.
- When you change this setting, the current Cardinal Snapping filter settings are shown as the numerical coordinates on the stick you're adjusting.
- The scale goes from `-1` to `6`, and defaults to `6`.
- At `-1` the stick will snap _away_ from the cardinal so that the stick cannot output `1.0` cardinals at all.
- At `0`, the stick will not snap to cardinals at all. This is equivalent to OEM cardinal behavior.
- Between `1-6`, the stick will snap to the cardinal from that far away in both positive and negative directions.
---
## Axis Smoothing Adjustment
**Button Combo (Analog Stick):** `R+X/Y+Du/Dd`
**Button Combo (C-Stick):** `R+Z+X/Y+Du/Dd`
Button combos for adjusting values for the C-Stick are the same as for the analog stick, with an added press of the `Z` button.
Axis Smoothing is just a simple low-pass filter similar to a capacitor on a vanilla Gamecube controller. Increasing this setting slightly reduces responsiveness. If you have the Smart Snapback Filter disabled, you can use this to suppress snapback, or use both in conjunction if your snapback is really strong (though in these cases, it's often better to try and solve the problem from a mechanical angle).
- Press `R+(Z)` for your stick, `X/Y` for your axis, and `D-pad up/down` to increase/decrease
- Example: `R+(Z)+X+Du` strengthens the effect on the X axis, and `R+(Z)+Y+Dd` reduces the effect on the Y axis.
- When you change this setting, the current Axis Smoothing filter settings are shown as the numerical coordinates on the stick you're adjusting.
- The scale goes from `0-9`, and defaults to `0`.
- `0` disables axis smoothing entirely.
Press `R+Start` while in config mode to display the axis smoothing values on each stick.
---
## Input Consistency Mode Toggle
**Button Combo:** `A+Z+Start`
Cycles the input consistency setting through its three modes and displays which mode is currently active on the analog stick's Y axis:
- `-69`: Disabled, same behavior as any other USB controller connected to the Nintendo Switch. Not recommended.
- `42`: "Consistency" mode, aims to improve input consistency at the cost of $\leq 333\mathrm{\mu s}$ input latency compared to "regular" mode - default setting.
- `69`: "Super Hack" mode, aims to improve input latency at a slight cost of input consistency compared to "consistency" mode. Currently experimental, not (yet) recommended for tournaments.
For more information about the different input consistency modes, consult the [Input Consistency Mode](./input-consistency.md#input-consistency-modes) list.
---
## Display Values
Display waveshaping values on each stick: `L+Start`
Display axis smoothing values on each stick: `R+Start`
Display smart snapback values on each stick: `Du+Start`

76
src/input-consistency.md Normal file
View file

@ -0,0 +1,76 @@
# On Polling and Input Consistency
This is a rather technical document about USB polling, input latency, and the issues that arise with input consistency. If you only care about the NaxGCC's solutions to this problem, and not the background knowledge, you can skip ahead to the [Input Consistency Modes](#input-consistency-modes) section.
## General Info
The vast majority of human interface devices (HIDs) transmit their states over USB using a technique known as "polling". Essentially, these devices (clients) advertise themselves as supporting a certain polling interval/frequency to whatever device they're attached to (hosts). The host then polls the client at the desired frequency, or at a lower one (= not as often, = more slowly) if the host doesn't support the client's desired frequency.
The Nintendo Switch supports polling USB devices at up to $125\mathrm{Hz}$, or once every $8\mathrm{ms}$. A game running at $60\mathrm{fps}$ takes $\approx16.66\mathrm{ms}$ to draw a frame, meaning with a polling rate of $8\mathrm{ms}$, a USB device would be able to update its state _up to_ 3 times per frame. Notice how I said "up to", because this is where things start to get wonky.
The reason it's "up to 3 times" and not "3 times, period" is because the USB polling and the game's frame draws are not in sync. Otherwise, a polling interval of $\approx16.66\mathrm{ms}$ would be perfectly sufficient, provided the host polls the adapter right before the frame is supposed to be drawn$^1$. Due to technical reasons, this is not possible however, so we are stuck with two asynchronous intervals: Polling & frame draws.
$^1$even if the host didn't poll the adapter right before the frame is drawn, it would still be fine, because as long as the polling interval is a multiple of the frame draw time, at least input _integrity_ would be guaranteed, even if _latency_ could still be variable depending on when your device was plugged in
## Input Integrity
Now, what does this mean for your input integrity? Essentially, in a system where polling intervals are _not_ multiples of each other, the time window in which your inputs are _guaranteed_ to come out on the frame you'd expect them to is equal to $T_f-T_p$ where $T_f$ is the time it takes to draw a frame ($\approx16.66\mathrm{ms}$) and $T_p$ is the polling interval ($8\mathrm{ms}$). So, on the Nintendo Switch, where USB polling is locked $8\mathrm{ms}$ and frame time of Smash Ultimate is $\approx16.66\mathrm{ms}$, our window of time during which inputs are _guaranteed_ to come out on the _expected_ frame is $16.\overline{6}\mathrm{ms} - 8\mathrm{ms} = 8.\overline{6}\mathrm{ms}$
This then means that during the first $\approx8.66\mathrm{ms}$ of a "frame capture window", your input is guaranteed to come out on the frame you'd expect (the one whose frame capture window is currently open). For any input, the probability $p(n)$ that your input will arrive at the expected frame, for any $n$ that is the time elapsed (in ms) since the start of the frame capture window, is $p(n) = \frac{T_f - n}{T_p}$. As you can see, for $n \leq T_f - T_p, p(n) \geq 1 \rightarrow p(n) = 1$, and for $n \gt T_f - T_p, p(n) \lt 1$.
In plain English, with a game running at $60\mathrm{fps}$ and USB polling at $8\mathrm{ms}$, you have an $\approx8.66\mathrm{ms}$ (slightly more than half a frame) window where your inputs are guaranteed to be consistent, everything outside that window is RNG to varying degrees, whether your input will be delayed by a frame or not.
Now, using this we can calculate the overally probability that any input may be delayed by a frame, assuming a uniform distribution of inputs within the frame capture window. As we discussed before, for any $n \lt T_f - T_p, p(n) = 1$, and for any $n \geq T_f - T_p, p(n) = \frac{T_f - n}{T_p}$. Since the probability that your input is delayed increases linearly the closer you get to the end of the frame capture window, we can establish that the average of all $p(n)$ where $T_f - T_p \lt n \lt T_f$ is $0.5$, and we can calculate the overall probability that your input is coming out on the _expected_ frame like so: $\frac{8.\overline{6}}{16.\overline{6}} \times 1 + \frac{8}{16.\overline{6}} \times 0.5 \approx 75.99\%$. This means that, in turn, every input you make has a $\approx24.01\%$ chance of being delayed by a frame.
However, that's not the end of it...
## Joybus
See, the math above assumes that the GCC adapter is the device providing the inputs to the console. However, it is only a middleware, and the true source of your inputs is your controller. The GameCube controller interacts with the GCC adapter pretty much the same as with the OG GameCube, using the [joybus](https://www.int03.co.uk/crema/hardware/gamecube/gc-control.html) protocol, which is the same protocol that N64 controllers use. And its age shows, it doesn't have differential signalling, checksumming, or any of the other goodies other, more modern protocols (like USB) have.
But worst of all, it comes with yet another polling rate. Originally, the joybus protocol is polled at $6\mathrm{ms}$ intervals, which would be catastrophic in this case. Luckily, the original GCC adapter made by Nintendo appears to poll at $1.2\mathrm{ms}$ instead. Still not great, but better. Now, you might be thinking to yourself _"but Naxdy, $1.2\mathrm{ms}$ is less than $8\mathrm{ms}$, so surely this is a good thing?"_ well yes, but no. It _would_ be a good thing, if the GCC could be connected to the Nintendo Switch directly, but it cannot, it _has_ to go through the adapter, which has its own polling rate of 8ms.
So, you end up with a system with three independent polling rates: The Switch polls the adapter at $8\mathrm{ms}$ intervals, and the adapter polls the controller at $1.2\mathrm{ms}$ intervals, and then the controller has whatever scan rate it has (Phobs have a $1\mathrm{ms}$ scan interval FYI). Now, remember how the time frame in which your input is _guaranteed_ to come out on the expected frame was $T_f - T_p$, but what about a system with multiple polling rates? Well, in this case it's $T_f - \sum_{i=1}^nT_i$ where $n$ is the number of individual polling rates and $T_1, T_2, ..., T_n$ are the individual polling rates (in ms).
Again in plain English, if you have multiple polling rates, the frame window in which your inputs are _guaranteed_ to come out on the frame you'd expect them to, is the total time of the frame window minus the sum of all polling rates. So, let's do some addition and subtraction for our use case here: $16.\overline{6} - 8 - 1.2 - 1 = 6.4\overline{6}$. That's less than half a frame!
This is how it is when you're playing with a PhobGCC (the best GCC currently available) on a _first party_ GCC adapter from Nintendo. Note that third party adapters may very well be much worse than this, because they could poll the GCC at an even lower frequency (= more slowly).
**BONUS QUESTION:** What if the sum of all polling intervals is larger than the frame time window, i.e. $\sum_{i=1}^nT_i > T_f$ ? That's right, in this case your inputs are _always_ RNG! (good thing that's not the case here though)
## The Solution
Since the NaxGCC connects directly to the console and eliminates the joybus protocol entirely, there is no second polling rate. The scan rate of the NaxGCC's sticks is $1\mathrm{ms}$, and the buttons are scanned as quickly as the MCU allows (I've measured $\approx50\mu\mathrm{s}$ as the average ceiling $\gt 99.9\%$ of the time, with the worst outliers being $\approx100\mu\mathrm{s}$). While not quite reaching the $\approx8.66\mathrm{ms}$ window length, the sticks have a $\approx7.66\mathrm{ms}$ window of guaranteed input integrity, and the buttons are getting fairly close to $\approx8.56\mathrm{ms}$ at worst (more than half a frame).
This isn't the end of it though. NaxGCC connecting directly to the console brings another advantage with it, namely we can "trick" the console into sampling the controller at a different interval altogether, one that works to our advantage. We can actually pretend to be a "laggy" USB device, by artificially introducing a variable delay in order to ensure the controller actually sends its button state to the console every $\approx8.33\mathrm{ms}$ instead of every $8\mathrm{ms}$. Why $\approx8.33$? Because $\approx8.33$ is a divisor of $\approx16.66$ (the game's frame draw time), meaning the controller will be polled exactly twice as often as the game updates, and eliminating the chance of the polling intervals and the game's frame draw cycles offsetting to your disadvantage. This ensures that if you press and hold a button for $100\mathrm{ms}$ (exactly 6 frames), it will _always_$^1$ translate to 6 frames in-game (with polling at $8\mathrm{ms}$, there is a $\approx 24.01\%$ chance of it registering as 5 or 7 frames instead, as we established above).
$^1$unfortunately, due to real world limitations like timing jitter, this is not _always_ the case, but it is the case $\gt 98\%$ of the time, see below for more info
## The Experiment
So, what real-world impact does this have? I created a test in which I have the NaxGCC press and release a button, both in $100\mathrm{ms}$ intervals. Meaning the game should register 6 frames held, 6 frames released, 6 frames held, and so on. I used the [training mode modpack](https://github.com/jugeeya/UltimateTrainingModpack) to measure the exact number of frames the game actually recognizes the button as held / released. I let this test run for 10 minutes and recorded it to a video, then used a python script to go through every 6th frame and record what the game actually registered using optical character recognition.
When in "OG controller" mode, the inputs were about $\approx 75.25\%$ accurate meaning $\gt 24\%$ of the time, the game registered 5 or 7 frames held/released when it should have been 6. This is in line with our math from above. In "input consistency" mode, the accuracy was at $\approx 98.62\%$! So, with a NaxGCC, not only do you get the lowest latency possible, since you're eliminating any sort of middleware in form of an adapter, but you also get the highest input integrity possible.
The original full-length videos of the experiment are saved and uploaded to my YouTube channel, in case you'd like to cross-check the results:
- [OG controller mode](https://www.youtube.com/watch?v=UG7NFoMiE-Y)
- [Input consistency mode](https://www.youtube.com/watch?v=MNcWOTF9fLk)
# Input Consistency Modes
The NaxGCC features three separate input consistency modes, which can be [cycled through during controller configuration](./configuration.md#input-consistency-mode-toggle).
### Regular Mode
In regular mode, the NaxGCC will not attempt to modify the polling rate of the controller, and will instead send the controller's state to the console as soon as it is requested. This is the same behavior as the vast majority of other USB controllers and adapters when connected to the Nintendo Switch. This mode is not recommended for competitive play, as it carries a $\approx24.01\%$ chance of your inputs being misinterpreted.
### Consistency Mode
In consistency mode, the NaxGCC introduces a variable delay in order to wait responding to a poll request from the console until exactly $8.\overline{3}\mathrm{ms}$ (half a frame) have elapsed. This ensures that the controller is polled exactly twice as often as the game updates and (nearly) eliminates the chance of your inputs being misinterpreted. This is the recommended mode for competitive play, and is the default mode for the NaxGCC.
### "Super Hack" Mode
In "super hack" mode, the NaxGCC avoids responding to the console's poll requests until the controller state has changed, _and_ at least $8.\overline{3}\mathrm{ms}$ have elapsed since the last poll request. This ensures that, for inputs made more than $8.\overline{3}\mathrm{ms}$ apart, the latency is minimized, since the state is immediately dispatched to, and interpreted by, the console, at a slight cost to input integrity for inputs made less than $8.\overline{3}\mathrm{ms}$ apart. This mode is currently experimental, as it is still undergoing extensive testing, and is currently **not** recommended for competitive play.
**Note:** "Super Hack" does not refer to this being a hack that is super, but rather something that is super hacky, since this pretty much out of spec behavior for a USB device.

37
src/introduction.md Normal file
View file

@ -0,0 +1,37 @@
# Introduction
The **NaxGCC** is a GameCube-style controller built on the [PhobGCC](https://github.com/PhobGCC/PhobGCC-SW).
Like the PhobGCC, the NaxGCC uses hall effect sensors instead of potentiometers for stick input. Additionally, it connects directly to the console via USB, by pretending to be a GCC adapter with 1 controller (itself) connected. This eliminates one additional layer of polling, and thus reduces perceived latency and improves input consistency. The NaxGCC also features a special "input consistency mode" that even further improves input consistency, beyond what is delivered by any other controller / adapter.
### Key Aspects
Click on any of these to expand.
<details><summary><strong>NaxGCC has all the important PhobGCC features.</strong></summary>
The hardware of NaxGCC is directly forked from PhobGCC's, meaning it benefits from the same improvements over a "regular" GCC, most importantly the fact that it uses hall-effect sensors instead of potentiometers for reading your stick positions.
Furthermore, large parts of its firmware have also been taken from PhobGCC's firmware, such as the snapback filter, cardinal snapping, and notch remapping to name a few. If you're used to calibrating a PhobGCC, you will have no trouble here.
</details>
<details><summary><strong>Provides both the lowest latency of any Switch controller, as well as the best input integrity.</strong></summary>
Because the NaxGCC connects directly to the console via USB, it already outperforms any controller that has to go through an adapter in terms of input latency.
Further, the NaxGCC has a special "input consistency" mode (enabled by default), which ensures a $\gt 98\%$ input accuracy, compared to $\lt 75\%$ for any other controller (worse if there is an adapter in the mix, with the exception of the Lossless Adapter).
For details on how it works, have a look at our wiki.
</details>
<details><summary><strong>Compatible with Phob hardware.</strong></summary>
The NaxGCC firmware is compatible with regular Phob 2.0 boards (those using an RP2040 microcontroller), since it's originally forked from the PhobGCC project. This means that if you are willing and able to slightly modify your controller shell to allow a micro USB cable to connect to your Phob board during play, you can turn your existing PhobGCC into a NaxGCC at no extra cost!
</details>
### What to find here
This book is the central source of information when it comes to the NaxGCC. Anything from user guides to information for hardware manufacturing / modding can be found here.

View file

@ -0,0 +1 @@
# JLCPCB Parts Ordering

1
src/phob2-to-naxgcc.md Normal file
View file

@ -0,0 +1 @@
# Phob2.0 -&gt; NaxGCC Conversion

25
src/update-firmware.md Normal file
View file

@ -0,0 +1,25 @@
# Updating Controller Firmware
Keeping your firmware up-to-date is recommended to ensure you benefit from the latest features, fixes, and improvements to performance. New versions of the firmware are published at the [official NaxGCC-FW repo's release page](https://git.naxdy.org/NaxdyOrg/NaxGCC-FW/releases)
> **NOTE:** Take care not to accidentally download the _nightly_ release, as these are experimental and may not be stable, unless you want to be a guinea pig for new features.
## Flashing your controller for the first time
If your controller is brand new and has never been used before, you will need to flash the firmware onto it. This is a one-time process, and you will not need to do it again unless you want to update the firmware.
Simply plug in your NaxGCC to your computer. It will show up as a regular mass-storage device, similar to a USB stick, or an SD card. Drag & drop the firmware binary (the file ending in `.uf2`) onto the device. The mass-storage device will disappear, and your NaxGCC is now ready to use!
## Updating your firmware
If you already have a controller with firmware on it, updating is easy. Simply plug in your NaxGCC to your computer while keeping the `A+X+Y` buttons held. The controller will show up as a mass-storage device, similar to when you first plugged it in. Drag & drop the new firmware binary onto the device, and you're done!
> **NOTE:** Major firmware updates (e.g. `1.x.x` to `2.x.x`), **WILL** cause your configuration and calibration to be reset! For these updates, it is recommended to write down your config values for things such as snapback, stick smoothing, etc. before updating. Also make sure to set aside some time to recalibrate your sticks after updating.
>
> Minor firmware updates (e.g. `1.0.x` to `1.1.x`) and fix updates (e.g. `1.0.0` to `1.0.1`) will not cause your configuration to be reset, and you can safely update without having to recalibrate.
## Downgrading your firmware
If you ever need to downgrade your firmware, the process is the same as updating. Simply plug in your NaxGCC to your computer while keeping the `A+X+Y` buttons held. The controller will show up as a mass-storage device, similar to when you first plugged it in. Drag & drop the old firmware binary onto the device, and you're done!
> **NOTE:** The same rules as for updating apply here. Major downgrades will cause your configuration and calibration to be reset, while minor downgrades and fix downgrades will not.