@@ -91,44 +91,145 @@ constexpr BitMap ClassicController_Shared::MapsHR::ButtonHome;
9191 * to copy the mapping name twice.
9292 *
9393 * If the controller is not in "high resolution" mode (according to the class
94- * data), return the controlData or controlBit function for the specified map
95- * in the "standard" maps (Maps::). If the controller *is* in "high resolution"
96- * mode, return the controlData or controlBit function for the specified map
97- * of the same name in the "high resolution" maps (MapsHR::).
94+ * data), fetch the controlData or controlBit function for the specified map
95+ * in the "standard" maps (Maps::) and bit shift to the left in order to fit
96+ * the full width of the "high res" data range. If the controller *is* in
97+ * "high resolution" mode, fetch the controlData or controlBit function for
98+ * the specified mapof the same name in the "high resolution" maps (MapsHR::).
9899 */
99- #define HRDATA (map ) !highRes ? getControlData(Maps::map) : getControlData(MapsHR::map)
100+ #define HRDATA (map, shift ) !highRes ? ( getControlData(Maps::map) << shift) & 0xFF : getControlData(MapsHR::map)
100101#define HRBIT (map ) !highRes ? getControlBit(Maps::map) : getControlBit(MapsHR::map)
101102
102103
103- boolean ClassicController_Shared::setHighRes (boolean hr) {
104+ boolean ClassicController_Shared::specificInit () {
105+ /* On init, try to set the controller to work in "high resolution" mode so
106+ * we get a full byte of data for each analog input. Then read the current
107+ * "data mode" from the controller so that the control surface functions
108+ * use the correct mappings. This way, the class flexes to support
109+ * all controllers regardless of their available data mode.
110+ *
111+ * This function will only return false if there is a *communciation error*
112+ * on the I2C bus, meaning that the controller did not respond to a write
113+ * or did not provide the right amount of data for a request. It will *not*
114+ * return false if the "high resolution" mode is not successfully set.
115+ */
116+ delayMicroseconds (I2C_ConversionDelay); // wait after ID read before writing register
117+ return setDataMode (true ); // try to set 'high res' mode. 'success' if no comms errors
118+ }
119+
120+ boolean ClassicController_Shared::checkDataMode (boolean *hr) const {
121+ /* Programmator Emptor: vvv This is where all of the headaches stem from vvv */
122+
123+ /* Okay, so here's the deal. The Wii Classic Controller reports its data
124+ * as six bytes with bit-packing for the analog values. When the NES and
125+ * SNES mini consoles were released it turned out that Nintendo had
126+ * included a "high resolution" mode for the Classic Controller. Writing
127+ * '0x03' to the register '0xFE' will make the controller output 8 bytes,
128+ * with each analog control surface using a full byte for its output.
129+ *
130+ * So here's the rub:
131+ * * Bad knockoff Classic Controllers only support "normal" mode
132+ * * Bad knockoff NES Controllers only support "high resolution" mode
133+ * * Genuine controllers support both
134+ *
135+ * Some knockoffs will behave properly and switch between the modes as
136+ * requested, but many will only report their data in one mode and ignore
137+ * the host if it asks otherwise. This results in control data that is
138+ * misinterpreted and users that are unhappy. So not only do we have to
139+ * switch between modes, but we need to come up with a robust method
140+ * to figure out *what mode we're in*.
141+ *
142+ * Here's my idea: in "standard" mode, the controller outputs 6 bytes of
143+ * control data, leaving bytes 7-8 blank (0x00). If we read these two bytes
144+ * and they have data in them, the controller must be in high resolution
145+ * mode! In theory, at least.
146+ *
147+ * This is complicated by the fact that the data from the I2C bus has no
148+ * error checking and is open drain, so if the pull-ups are too weak or
149+ * there is noise on the bus some of these bits may flip 'high' and then
150+ * the check is no good.
151+ *
152+ * To mitigate this, the same data set is requested twice and compared
153+ * against itself. If there is a data mismatch, the requests are repeated
154+ * until the two arrays agree. Not perfect, but better than nothing.
155+ *
156+ * Note that this read starts at 0x00. I tried starting at where the data
157+ * *actually starts* (bytes 7 and 8, i.e. ptr 0x06), but the knockoff
158+ * controllers apparently don't understand how to act as a proper
159+ * register-based I2C device and just return junk. So instead we're starting
160+ * at the beginning of the data block.
161+ */
162+ static const uint8_t CheckPtr = 0x00 ; // start of the control data block
163+ static const uint8_t CheckSize = 8 ; // 8 bytes to cover both std and high res
164+ static const uint8_t DataOffset = 0x06 ; // start of the data we're interested in (7 / 8)
165+ uint8_t checkData[CheckSize] = { 0x00 }, verifyData[CheckSize] = { 0x00 };
166+ do {
167+ if (!requestData (CheckPtr, CheckSize, checkData)) return false ;
168+ delayMicroseconds (I2C_ConversionDelay); // need a brief delay between reads
169+ if (!requestData (CheckPtr, CheckSize, verifyData)) return false ;
170+
171+ boolean equal = true ;
172+ for (uint8_t i = 0 ; i < CheckSize - DataOffset; i++) {
173+ if (checkData[i] != verifyData[i]) {
174+ equal = false ; // one byte does not match! quit
175+ break ;
176+ }
177+ }
178+
179+ if (equal) break ; // if data matches, continue
180+ delayMicroseconds (I2C_ConversionDelay); // if we're doing another loop, wait between reads again
181+ } while (true );
182+
183+ *hr = !(checkData[DataOffset] == 0x00 && checkData[DataOffset+1 ] == 0x00 ); // if both are '0', high res is false
184+ return true ; // successfully read state
185+ }
186+
187+ boolean ClassicController_Shared::setDataMode (boolean hr, boolean verify) {
104188 const uint8_t regVal = hr ? 0x03 : 0x01 ; // 0x03 for high res, 0x01 for standard
105- boolean success = writeRegister (0xFE , regVal); // write to controller
106- if (success == true ) {
107- highRes = hr; // save 'high res' setting
108- if (highRes == true && getRequestSize () < 8 ) setRequestSize (8 ); // 8 bytes needed for hr mode
109- else if (highRes == false ) setRequestSize (MinRequestSize); // if not in HR, set back to min
189+ if (!writeRegister (0xFE , regVal)) return false ; // write to controller
190+
191+ if (verify == true ) {
192+ boolean currentMode = false ; // check controller's HR setting
193+ if (!checkDataMode (¤tMode)) return false ; // error: could not read mode
194+ highRes = currentMode; // save current mode to class
195+ }
196+ else {
197+ highRes = hr; // save mode (no verification)
198+ }
199+
200+ if (getHighRes () == true && getRequestSize () < 8 ) {
201+ setRequestSize (8 ); // 8 bytes needed for hr mode
202+ }
203+ else if (getHighRes () == false && hr == false ) {
204+ setRequestSize (MinRequestSize); // if not in HR and *trying* not to be, set back to min
110205 }
111- return success;
206+
207+ return true ; // 'success' if no communication errors, regardless of setting
208+ }
209+
210+ boolean ClassicController_Shared::setHighRes (boolean hr, boolean verify) {
211+ // 'success' if the mode is changed to the one we're trying to set
212+ return setDataMode (hr, verify) && (getHighRes () == hr);
112213}
113214
114215boolean ClassicController_Shared::getHighRes () const {
115216 return highRes;
116217}
117218
118219uint8_t ClassicController_Shared::leftJoyX () const {
119- return HRDATA (LeftJoyX);
220+ return HRDATA (LeftJoyX, 2 ); // 6 bits for standard range, so shift left (8-6)
120221}
121222
122223uint8_t ClassicController_Shared::leftJoyY () const {
123- return HRDATA (LeftJoyY);
224+ return HRDATA (LeftJoyY, 2 );
124225}
125226
126227uint8_t ClassicController_Shared::rightJoyX () const {
127- return HRDATA (RightJoyX);
228+ return HRDATA (RightJoyX, 3 ); // 5 bits for standard range, so shift left (8-5)
128229}
129230
130231uint8_t ClassicController_Shared::rightJoyY () const {
131- return HRDATA (RightJoyY);
232+ return HRDATA (RightJoyY, 3 );
132233}
133234
134235boolean ClassicController_Shared::dpadUp () const {
@@ -164,11 +265,11 @@ boolean ClassicController_Shared::buttonY() const {
164265}
165266
166267uint8_t ClassicController_Shared::triggerL () const {
167- return HRDATA (TriggerL);
268+ return HRDATA (TriggerL, 3 ); // 5 bits for standard range, so shift left (8-5)
168269}
169270
170271uint8_t ClassicController_Shared::triggerR () const {
171- return HRDATA (TriggerR);
272+ return HRDATA (TriggerR, 3 );
172273}
173274
174275boolean ClassicController_Shared::buttonL () const {
@@ -244,21 +345,14 @@ void ClassicController_Shared::printDebug(Print& output) const {
244345 zlButtonPrint, zrButtonPrint);
245346
246347 output.print (buffer);
247- if (getHighRes ()) output.print (" (High Res )" );
348+ if (getHighRes ()) output.print (" | (HR )" );
248349
249350 output.println ();
250351}
251352
252353
253354// ######### Mini Controller Support #########
254355
255- boolean MiniControllerBase::specificInit () {
256- // all mini controllers use high res format, and some of the cheaper third
257- // party ones will not work without it. So we're going to set this on
258- // connection for all of them
259- return setHighRes (true );
260- }
261-
262356void NESMiniController_Shared::printDebug (Print& output) const {
263357 const char fillCharacter = ' _' ;
264358
0 commit comments