Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drawsome Tablet #57

Merged
merged 10 commits into from
May 25, 2020
Merged

Drawsome Tablet #57

merged 10 commits into from
May 25, 2020

Conversation

nullstalgia
Copy link
Contributor

@nullstalgia nullstalgia commented Mar 22, 2020

So, it's quite a bit simpler than the uDraw, but I think I prefer it... minus the magic address writing that has to be done.

Anyway, this is tested and working so far.

(Tested with this added to NXC_Comms.h

// Extension controller specific I2C functions
// -------------------------------------------
// Control Data
inline boolean initialize(NXC_I2C_TYPE &i2c) {
	/* Initialization for unencrypted communication.
	* *Should* work on all devices, genuine + 3rd party.
	* See http://wiibrew.org/wiki/Wiimote/Extension_Controllers
	*/
	if (!i2c_writeRegister(i2c, I2C_Addr, 0xF0, 0x55)) { return false; }
	delay(10);
	if (!i2c_writeRegister(i2c, I2C_Addr, 0xFB, 0x00)) { return false; }
	delay(20);
	if (!i2c_writeRegister(i2c, I2C_Addr, 0xFB, 0x01)) { return false; }
	delay(10);
	if (!i2c_writeRegister(i2c, I2C_Addr, 0xF0, 0x55)) { return false; }
	delay(20);
	return true;
}

)


Some notes:

1. The X and Y mapping they use is different.

image
image

(Photos from Raphnet)

Y is flipped.

2. When the pen is off the surface, uDraw sets it to an impossible value. Drawsome leaves at at previous.

3. Neither tablet uses the whole range of the allocated bytes given for pressure/x/y, etc. Should we document this somewhere, using the values provided by raphnet/our own testing?

@dmadison
Copy link
Owner

Raphnet link for reference: https://www.raphnet.net/divers/wii_graphics_tablets/index_en.php

My strategy so far has been to be very laissez-faire with the data, so the library just acts as a go-between and doesn't assume how the user wants to use it. The difference in the tablet origins is important, and I think it should be documented as a comment in the source.

Neither tablet uses the whole range of the allocated bytes given for pressure/x/y, etc. Should we document this somewhere, using the values provided by raphnet/our own testing?

I haven't been, just because it's presumably slightly different for each individual controller. The two genuine Nunchuks I have for instance use wildly different min/max points for each joystick axis and accelerometer while the third party Nunchuk I have makes full use of the entire joystick range.

My assumption is that if you're trying to use the library for any given controller, you have a physical copy of that controller and you can see the range of your particular device while testing. But maybe that's a bad assumption.

Since I doubt there's a knockoff "Drawsome" tablet out there it wouldn't hurt to add a "typical" range comment to the example and the header.


As for changes, make sure you update the range comments in the "Demo" example to match the range of the new data maps. And be sure to change the xCoordinate and yCoordinate vars in that example to use uint16_t so they don't have the possibility to overflow.

I'll see if I can set aside some time this week to try and integrate the extra registry writes into the communication flow.


I saw your message on Twitter. DM'd you there :)

@nullstalgia
Copy link
Contributor Author

Any update on getting the extra write bytes going? :)

@dmadison
Copy link
Owner

Not yet. I've been busy with other projects, and I'm still not quite sure how I want to integrate the extra register writes into the program flow.

@dmadison
Copy link
Owner

Fiddling a bit with this now. I'm thinking the best way to do the extra register writes is to have a virtual function as part of the connect() flow that is then overridden by each controller class in turn. In theory all controller types would maintain the same API and the extra writes would be transparent to the end user for single controller instances.

The sticking point here is using multiple controllers at the same time. In that case, the ExtensionPort class won't use the controller-specific connect functions so they'll have to be called manually by the user. And it can't be based on the controller's ID because that's unique to the type but not necessarily the behavior (e.g. the "high resolution" mode of the Classic Controller shares the same ID as the "normal" mode). You'll end up with something like this:

ExtensionPort port;
ClassicController classic(port);
DrawsomeTablet tablet(port);

boolean connected = false;

void setup() {
	port.begin();
}

void loop() {
	if(!connected && port.connect()) {
		switch(port.getControllerType()) {
			case(ExtensionType::ClassicController):
				connected = classic.customInit();
				break;
			case(ExtensionType::DrawsomeTablet):
				connected = tablet.customInit();
				break;
		}
	}
	// reading controller data follows	
}

Which technically works, but it's neither pretty nor intuitive.

Any thoughts? Or ideas on the name for the function?

@nullstalgia
Copy link
Contributor Author

Hmm. The first thing that comes to mind, is to possibly pass either the object or a way to differentiate it, then having it run the customInit there.

But.. that would be a little abstract/require per-controller overrides...

Another issue I personally see with this, is that it'd be a little wasteful to run the customInit each time. (I know it's an example, but I feel it's a point that needs to be stated)

Especially with how undocumented this all is, I'm not sure how the controllers would react to having that mode set again and again. Then again, I could be talking out of my butt.

I'm not totally against it, especially since you do something similar in examples/Any/MultipleTypes/MultipleTypes.ino.

I'll ask around to see if anyone can think of a better solution


As for the naming, I feel customInit sounds almost too friendly? Like it almost sounds optional. (Which, it is for the ClassicController, but still)


And, a thought just blipped into my head. We've been using certain min-maxes for the ClassicController for a hot while.

Are you planning on possibly breaking the old programs that have hardcoded ranges? Making it optional via a flag controller.useHDMode(true)? Or possibly, making a copy of the ClassicController type that does the customInit all the time?

@dmadison
Copy link
Owner

Hmm. The first thing that comes to mind, is to possibly pass either the object or a way to differentiate it, then having it run the customInit there.

Sure, although at that point you're just hiding that switch in another function. You'd still have to break the typical program flow to call it (and know when to you need to call it).

Like I said, the custom initialization(s) would be virtual if you're calling the connect() function directly on controllers of that type. It only breaks down if you're using multiple controller instances and call the generic "port" manager on that bus instead of the object directly.

Another issue I personally see with this, is that it'd be a little wasteful to run the customInit each time. (I know it's an example, but I feel it's a point that needs to be stated)

I'm not sure what you mean here. You would only run the custom initialization once, on connection.

As for the naming, I feel customInit sounds almost too friendly? Like it almost sounds optional.

That's a fair point. I'm having trouble coming up with a name that fits well, although I do like the 'init' keyword as a part of it. Perhaps specificInit? controllerInit is too generic. The begin keyword is already used for the I2C configuration, setup is already used by the Arduino function and intuitively seems like it would be called before connect().

Are you planning on possibly breaking the old programs that have hardcoded ranges? Making it optional via a flag controller.useHDMode(true)? Or possibly, making a copy of the ClassicController type that does the customInit all the time?

That's a different topic - at the moment I'm just talking about adjusting the library's comm flow to work with extra register writes during initialization.

I haven't gotten to it yet, but the "high res" Classic Controller implementation will likely end up as its own class, separate from the current one.

@nullstalgia
Copy link
Contributor Author

nullstalgia commented May 11, 2020

It only breaks down if you're using multiple controller instances and call the generic "port" manager on that bus instead of the object directly.

Again, having a similar syntax to the previous example, in my eyes, gives it a bit of a pass. That's just me, however. Plus it can look a little unruly. I'll let you know if I think of something.

I'm not sure what you mean here. You would only run the custom initialization once, on connection.

I totally missed the !connected My bad.

That's a fair point. I'm having trouble coming up with a name that fits well

At this point, magicInit would be okay.

Maybe something like special or specialized?

The tablet requires two additional register writes before it will start sending control data. The library now supports this functionality without issue (yay!).

See the notes here: https://www.raphnet.net/divers/wii_graphics_tablets/index_en.php
This function was removed in the latest pull request. connect() is now used for both connection and reconnection attempts.
@dmadison
Copy link
Owner

Sorry for the long wait. The library now has the functionality to add those extra registry writes. Give those examples a try and let me know how it goes.

@nullstalgia
Copy link
Contributor Author

Tested the branch with just the tablet, and it works perfectly! :)

Great job!

@dmadison dmadison merged commit 4f130a3 into dmadison:master May 25, 2020
@dmadison
Copy link
Owner

Merged. Thank you!

dmadison added a commit that referenced this pull request May 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants