Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : PicoMiteVGA/CMM2: Controller API
Page 1 of 2 | |||||
Author | Message | ||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3807 |
Hi folks, I'm putting the finishing touches to my Controller API for the PicoMiteVGA (more specifically the PicoGAME VGA) and the CMM2 but I have some questions regarding hardware I don't have access to that maybe someone can help me with ? As it stands "out of the box" the code I am providing supports the following: PicoMiteVGA / PicoGAME - Port A: Atari 1-button Joystick - Port B: Atari 1-button Joystick - Port A: NES clone gamepad (9 pin) - Port B: NES clone gamepad (9 pin) - Port A: SNES clone gamepad (9 pin) - Port B: SNES clone gamepad (9 pin) - Keyboard: Cursor keys & Space to fire CMM2 - G1: Wii Classic gamepad (I2C channel 3) - G2 - port 1: Wii Classic gamepad (I2C channel 3) - G2 - port 2: Wii Classic gamepad (I2C channel 1) - G2 DX: Atari 1-button Joystick (though the DX is wired for 2-buttons which is supported if such a joystick can be found) - Keyboard: Cursor keys & Space to fire MMB4W - Keyboard: Cursor keys & Space to fire This is all extensible with user written "drivers" in MMBasic (or as CSUBs) you just have to implement a simple "read" sub and optional "open" and "close" subs, e.g. the "driver" for the G2 DX Atari Joystick looks like this: Sub atari_dx_open() SetPin 32, Din, PullUp SetPin 33, Din, PullUp SetPin 35, Din, PullUp SetPin 36, Din, PullUp SetPin 38, Din, PullUp SetPin 40, Din, PullUp End Sub Sub atari_dx%(bits%) bits% = Not Pin(32) * ctrl.A% Inc bits%, Not Pin(33) * ctrl.B% Inc bits%, Not Pin(35) * ctrl.UP% Inc bits%, Not Pin(36) * ctrl.DOWN% Inc bits%, Not Pin(38) * ctrl.LEFT% Inc bits%, Not Pin(40) * ctrl.RIGHT% End Sub Note I'm only supporting digital controllers at this time, analog support could be added as a separate "analog read" sub but it's out-of-scope at the moment. My questions are: 1. Which I2C channels are the 3 Nunchuck ports on Piotr's Colour Maximite 2 Deluxe Edition GEN2 wired to ? Is it port 1 => channel 3, port 2 => channel 1, port 3 => channel 2, or something else ? 2. Which I2C channels are the 2 Nunchuck ports on CG's RetroMax G2 wired to ? 3. Have I missed any other "standard" PicoMite or CMM2 digital controller configurations ? Best wishes, Tom Edited 2022-11-03 19:43 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Mixtel90 Guru Joined: 05/10/2019 Location: United KingdomPosts: 5643 |
I'm pretty sure that all Nunchucks are at the fixed address of 0x52 so you can only have one per I2C port. Does that help? Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3807 |
Not really . As far as I understand it (which is admittedly "not a lot") each physical Nunchuck port on the board is accessed via a different channel 1..3, see the CMM2 documentation for I2C and CONTROLLER CLASSIC OPEN. On the G1, the single exposed port is documented as being connected to I2C channel 3. On the "standard" G2, by experimentation the left-hand port is connected to I2C channel 3 and the right-hand port is connected to I2C channel 1. What I don't know is what the hardware port -> channel mapping is on the RetroMax (2 ports) or CMM2 DX G2 (3 ports). TBH it's really just a "nice to know" since the software doesn't care unless you want to show a helpful message to the user which refers to the hardware port locations rather than the I2C channels. Best wishes, Tom Edited 2022-11-03 21:21 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Turbo46 Guru Joined: 24/12/2017 Location: AustraliaPosts: 1584 |
Hi Tom, I found this Document for Poitr's Deluxe by Mike Kopack (thanks Mike) which says in part: For the Retromax: A photo at this link shows that Nuncuk 2 is on I2C1. Hope that helps. Bill Keep safe. Live long and prosper. |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3807 |
Thanks for the detective work Bill, that answers my questions. Best wishes, Tom Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Turbo46 Guru Joined: 24/12/2017 Location: AustraliaPosts: 1584 |
Not sure about that now. While the schematic agrees with document in the link when I tested a Nunchuk on channel 3: 'Check for Wii Nunchuk function GotNun%() On Error Skip 1 controller Nunchuk Open 3 if mm.errno = 0 then if Nunchuk(T) = &HA4200000 Then GotNun% = 1 end if End function It works on Nunchuk port 3 on the front panel. Maybe it has been changed so that the Nunchuk number reflects the I2C port to which it is connected to? Or I'm doing something stupid. Note: The Nunchuk ports on Poitr's Deluxe are upside down compared to the original CMM2. Bill Keep safe. Live long and prosper. |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3807 |
Hi Bill, Just to be clear are you saying that on the DX the 3 Nunchuck ports (1,2,3) are mapped to i2c channels (1, 2, 3) respectively and not (3, 1, 2) as we (?) originally thought? Best wishes, Tom Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Turbo46 Guru Joined: 24/12/2017 Location: AustraliaPosts: 1584 |
Hi Tom, I wasn't really because I only tested channel 3 so I wrote the program below to test that and I can confirm that yes, the Nunchuk ports on the front of my CMM2 Deluxe numbered 1,2 and 3 line up with I2C channels 1,2 and 3 respectively. Personally, I think that just supporting the default channel 3 is all that is needed. ' ' Nunchuk test program do: LOOP UNTIL INKEY$ = "" ' Wait until empty PRINT "Please enter the Nunchuck channel number (1-3) "; do nc% = VAL(INKEY$) LOOP UNTIL nc% > 0 AND nc% < 4 PRINT nc% IF NOT GotNun%(nc%) THEN PRINT "Found no Nunchuk" END ENDIF do CLS PRINT "Press any key to stop" PRINT "Testing Nunchuc channel "; : PRINT nc% PRINT BIN$(ReadNun%(nc%),8) PRINT "RLDU--BA" PAUSE 250 LOOP UNTIL INKEY$ <> "" CloseNun(nc%) END 'Reads the Nunchuk as if it were a joystick FUNCTION ReadNun%(nc%) INC ReadNun%, nunchuk(z, nc%) = 1 'Fire A INC ReadNun%, (nunchuk(c, nc%) = 1) * 2 'Fire B INC ReadNun%, (nunchuk(jy, nc%) > 170) * 16 ' Up INC ReadNun%, (nunchuk(jy, nc%) < 90) * 32 ' Down INC ReadNun%, (nunchuk(jx, nc%) < 90) * 64 ' Left INC ReadNun%, (nunchuk(jx, nc%) > 170) * 128 ' Right END FUNCTION 'Close the nunchuk SUB CloseNun(nc%) controller nunchuk CLOSE nc% END SUB 'Check for Wii Nunchuk FUNCTION GotNun%(nc%) ON ERROR SKIP 1 controller Nunchuk OPEN nc% IF MM.ERRNO = 0 THEN IF Nunchuk(T, nc%) = &HA4200000 THEN GotNun% = 1 END IF END FUNCTION Keep safe. Live long and prosper. |
||||
Turbo46 Guru Joined: 24/12/2017 Location: AustraliaPosts: 1584 |
Here is a Nunchuk "driver" which imitates Tom's joystick "driver" above. It uses the default channel 3, function GotNun%() returns 'true' if it finds and opens a Nunchuk. function ReadNun%() inc ReadNun%, nunchuk(z) = 1 'Fire A inc ReadNun%, (nunchuk(c) = 1) * 2 'Fire B inc ReadNun%, (nunchuk(jy) > 170) * 16 ' Up inc ReadNun%, (nunchuk(jy) < 90) * 32 ' Down inc ReadNun%, (nunchuk(jx) < 90) * 64 ' Left inc ReadNun%, (nunchuk(jx) > 170) * 128 ' Right end function 'Close the nunchuk sub CloseNun controller nunchuk close end sub 'Check for Wii Nunchuk function GotNun%() On Error Skip 1 controller Nunchuk Open if mm.errno = 0 then if Nunchuk(T) = &HA4200000 Then GotNun% = 1 end if End function Bill Keep safe. Live long and prosper. |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3807 |
Thanks Bill, For the record the controller API has moved on, so that for example, The Atari joystick driver now looks like: ' Button values as returned by drivers subroutines. Const ctrl.R = &h01 Const ctrl.START = &h02 Const ctrl.HOME = &h04 Const ctrl.SELECT = &h08 Const ctrl.L = &h10 Const ctrl.DOWN = &h20 Const ctrl.RIGHT = &h40 Const ctrl.UP = &h80 Const ctrl.LEFT = &h100 Const ctrl.ZR = &h200 Const ctrl.X = &h400 Const ctrl.A = &h800 Const ctrl.Y = &h1000 Const ctrl.B = &h2000 Const ctrl.ZL = &h4000 Const ctrl.OPEN = -1 Const ctrl.CLOSE = -2 Const ctrl.SOFT_CLOSE = -3 ' Atari joystick port on CMM2 Deluxe G2. Sub atari_dx(x%) Select Case x% Case Is >= 0 x% = Not Pin(32) * ctrl.A Inc x%, Not Pin(33) * ctrl.B Inc x%, Not Pin(35) * ctrl.UP Inc x%, Not Pin(36) * ctrl.DOWN Inc x%, Not Pin(38) * ctrl.LEFT Inc x%, Not Pin(40) * ctrl.RIGHT Exit Sub Case ctrl.OPEN SetPin 32, Din, PullUp SetPin 33, Din, PullUp SetPin 35, Din, PullUp SetPin 36, Din, PullUp SetPin 38, Din, PullUp SetPin 40, Din, PullUp End Select End Sub And a Wii Classic driver looks like: ' Wii Classic gamepad on I2C3. Sub wii_classic_3(x%) If x% >= 0 Then x% = Classic(B, 3) If x% = &h7FFF Then x% = 0 ' Ignore this glitch. Exit Sub EndIf Static is_open% = 0 Select Case x% Case ctrl.OPEN If Not is_open% Then Controller Classic Open 3 : is_open% = 1 Case ctrl.CLOSE If is_open% Then Controller Classic Close 3 : is_open% = 0 Case ctrl.SOFT_CLOSE ' Do nothing End Select End Sub The key take aways are: 1. The constants for the results bitmap have changed to match those that the CMM2 manual documents for the Wii Classic controller. Previously they were aligned with the raw output from clocking an NES controller. 2. Drivers are now implemented as SUBs not FUNCTIONs, this facilitates them being replaced by CSUB implementations in the future. 3. There are no longer separate OPEN and CLOSE routines, at the cost of evaluating a SELECT CASE I decided it made more sense to be able to package each controller up in a single subroutine. The OPEN/CLOSE routines for the Wii Classic (and no doubt Nunchuck) are a bit "strange" because the i2c initialisation for these is relatively slow. This continues to be WIP. Best wishes, Tom Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Turbo46 Guru Joined: 24/12/2017 Location: AustraliaPosts: 1584 |
Thanks Tom, If I understand it correctly, operation of the joystick would be something like: ' ' Open Joystick atari_dx(ctrl.OPEN) ' or atari_dx(-1) ' for brevity ' ' To read the joystick: cntr% = 0 atari_dx(cntr%) ' Then the program must act on the value of cntr% ' That does require an extra step in a program (cntr% = 0) compared to using a function. But if the SUB can be converted to a CSUB then there must be a decent speed gain. Bill Keep safe. Live long and prosper. |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3807 |
Good morning (or evening) Bill, The expected use is something like: driver$ = "atari_dx" Call driver$, ctrl.OPEN Do While Not game_over% ' Game loop logic. ... ' Read controller. Call cntr$, result% ' Do something (e.g. SELECT CASE) with driver independent result%. ... Loop Call driver$, ctrl.CLOSE Then the only thing that needs to be changed to use a different controller is the value of driver$. No, it doesn't. Provided neither the calling code nor the driver code ever make cntr% negative you don't need to explicitly set it before calling the driver, this is because the first action of a driver when called with x% >= 0 should be to set that value, see: Sub atari_dx(x%) Select Case x% Case Is >= 0 x% = Not Pin(32) * ctrl.A ' <-- sets the value of the parameter. ... Best wishes, Tom Edited 2022-11-15 20:39 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
Turbo46 Guru Joined: 24/12/2017 Location: AustraliaPosts: 1584 |
Ha Ha, I should have known better. You're much too clever for me. I now hesitate to ask, but should you check the value of (T) to make sure you have the correct controller? Can you please tell me what version of the Classic controller you are using? Bill Keep safe. Live long and prosper. |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3807 |
On occasion too "clever" for me too . I currently don't have an actual Nunchuck to test with - it's on my Christmas list, so these are just educated guesses. Yes, as part of the OPEN action it should test the value is as expected and if not CLOSE the I2C channel and report an error. OR, the Wii driver could be rewritten such that it will service both Nunchuck and Classic, though obviously the user would require the Classic controller in order to generate the full spectrum of outputs. Does it have different versions, or do you just mean vendor ? The one I have is this: https://www.amazon.co.uk/gp/product/B07H9BKG1G/ref=ppx_yo_dt_b_asin_title_o05_s00?ie=UTF8&psc=1 Best wishes, Tom Edited 2022-11-15 20:58 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
PilotPirx Regular Member Joined: 03/11/2020 Location: GermanyPosts: 58 |
Please forgive my minimal Basic knowledge, but my stand in this regard has stopped at the Sinclair Spectrum. What is the functionality of the following code line: I have not found any references to Inc and ctrl. in the MMBasic manual. What do they do? Thanks a lot for any kind of info, Peter |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3807 |
Hi there, INC var [, increment] Should be in the manual. It increases the value of the variable by the increment, default 1 and can be negative. It is faster than var = var + increment because it involves one fewer variable lookups. ctrl.UP% is an integer constant defined earlier (as &h80), note that unlike most other BASICs you are allowed to use the period character '.' within an identifier. So that line says increment the value of bits% by &h80 if pin 35 is low. If the pin is high then bits% is incremented by 0, I believe this formulation is faster than using an IF or a CHOICE. Best wishes, Tom Edited 2022-11-15 23:27 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
PilotPirx Regular Member Joined: 03/11/2020 Location: GermanyPosts: 58 |
Hi Tom, thanks for the good explanation, but I checked again and found no explanation for the INC function in the Basic Manual (PicoMiteVGA and MMBasic Language Manual Ver. 4.5). It is neither a command nor a function. Are there hidden functions in the code? Edited 2022-11-16 00:59 by PilotPirx |
||||
thwill Guru Joined: 16/09/2019 Location: United KingdomPosts: 3807 |
Hi, ... It is neither a command nor a function. It's a command and is documented in the latest draft of the standard PicoMite manual, see link from this thread: https://www.thebackshed.com/forum/ViewTopic.php?TID=15140. It's absence from the PicoMiteVGA manual (and CMM2?) is either the result of an international conspiracy or human fallibility . Again excluding the possibility of international conspiracy I don't believe there is any intentionally hidden functionality ... though I have some familiarity with the source code and there are the occasional undocumented options to one or two commands/functions, presumably either for testing purposes, or as relics that were never "published". That version of the documentation is a relic, treat it with reverence but unless you are looking at one of the legacy 'mite platforms never look at it again. The "modern" 'mites (CMM2, PicoMite{VGA}, MMB4W and MMB4L) all use MMBasic 5.0.x - but you still need to be conscious of variations in platform specific commands/functions. Best wishes, Tom Edited 2022-11-16 02:21 by thwill Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
PilotPirx Regular Member Joined: 03/11/2020 Location: GermanyPosts: 58 |
Ashes on my head, I used old documents Learned something again... |
||||
Turbo46 Guru Joined: 24/12/2017 Location: AustraliaPosts: 1584 |
Regarding the controller, I was finding these, they have the same plug but are called 'Pro'. I don't know if they are compatible with the CMM2 or not. The manual says the (T) function code returns: &HA4200101=Classic, &HA4200402=Balance I don't know if it is the same as the classic or not. Probably doesn't matter, too many buttons for me anyway, I don't think I need one as long as the Nunchuk is supported. Bill Keep safe. Live long and prosper. |
||||
Page 1 of 2 |
Print this page |