Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 15:40 04 Dec 2022 Privacy Policy
Jump to

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 Kingdom
Posts: 2830
Posted: 09:42am 03 Nov 2022
Copy link to clipboard 
Print this post

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
CMM2 Welcome Tape, Creaky old text adventures
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 3139
Posted: 11:04am 03 Nov 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 2830
Posted: 11:20am 03 Nov 2022
Copy link to clipboard 
Print this post

  Mixtel90 said  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?


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
CMM2 Welcome Tape, Creaky old text adventures
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1120
Posted: 11:33pm 03 Nov 2022
Copy link to clipboard 
Print this post

Hi Tom, I found this  Document for Poitr's Deluxe by Mike Kopack (thanks Mike) which says in part:

  Quote  To write code to interface with ports 2 or 3, you’ll need to add in the optional I2C channel numbers of 1 and 2, respectively, in all the NUNCHUCK and CLASSIC commands/functions.


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 Kingdom
Posts: 2830
Posted: 10:46am 04 Nov 2022
Copy link to clipboard 
Print this post

Thanks for the detective work Bill, that answers my questions.

Best wishes,

Tom
CMM2 Welcome Tape, Creaky old text adventures
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1120
Posted: 10:35pm 12 Nov 2022
Copy link to clipboard 
Print this post

  Quote  To write code to interface with ports 2 or 3, you’ll need to add in the optional I2C channel numbers of 1 and 2, respectively, in all the NUNCHUCK and CLASSIC commands/functions.

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 Kingdom
Posts: 2830
Posted: 12:08pm 13 Nov 2022
Copy link to clipboard 
Print this post

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
CMM2 Welcome Tape, Creaky old text adventures
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1120
Posted: 02:12am 14 Nov 2022
Copy link to clipboard 
Print this post

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%
PRINT

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
 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: Australia
Posts: 1120
Posted: 02:42am 14 Nov 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 2830
Posted: 10:40am 14 Nov 2022
Copy link to clipboard 
Print this post

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
CMM2 Welcome Tape, Creaky old text adventures
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1120
Posted: 11:27pm 14 Nov 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 2830
Posted: 09:29am 15 Nov 2022
Copy link to clipboard 
Print this post

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$.

  Turbo46 said  That does require an extra step in a program (cntr% = 0) compared to using a function.


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
CMM2 Welcome Tape, Creaky old text adventures
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1120
Posted: 10:16am 15 Nov 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 2830
Posted: 10:32am 15 Nov 2022
Copy link to clipboard 
Print this post

  Turbo46 said  Ha Ha, I should have known better. You're much too clever for me.  


On occasion too "clever" for me too .

  Turbo46 said  I now hesitate to ask, but should you check the value of (T) to make sure you have the correct controller?


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.

  Quote  Can you please tell me what version of the Classic controller you are using?


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
CMM2 Welcome Tape, Creaky old text adventures
 
PilotPirx

Newbie

Joined: 03/11/2020
Location: Germany
Posts: 26
Posted: 01:04pm 15 Nov 2022
Copy link to clipboard 
Print this post

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:

  Quote   Inc bits%, Not Pin(35) * ctrl.UP%


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 Kingdom
Posts: 2830
Posted: 01:24pm 15 Nov 2022
Copy link to clipboard 
Print this post

  PilotPirx said  
  Quote   Inc bits%, Not Pin(35) * ctrl.UP%


I have not found any references to Inc and ctrl. in the MMBasic manual. What do they do?


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
CMM2 Welcome Tape, Creaky old text adventures
 
PilotPirx

Newbie

Joined: 03/11/2020
Location: Germany
Posts: 26
Posted: 02:58pm 15 Nov 2022
Copy link to clipboard 
Print this post

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 Kingdom
Posts: 2830
Posted: 03:46pm 15 Nov 2022
Copy link to clipboard 
Print this post

Hi,

  PilotPirx said  I checked again and found no explanation for the INC function in the Basic Manual (PicoMiteVGA ...

... 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 .

  PilotPirx said  Are there hidden functions in the code?


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".

  PilotPirx said  ... and MMBasic Language Manual Ver. 4.5).


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
CMM2 Welcome Tape, Creaky old text adventures
 
PilotPirx

Newbie

Joined: 03/11/2020
Location: Germany
Posts: 26
Posted: 04:24pm 15 Nov 2022
Copy link to clipboard 
Print this post

Ashes on my head, I used old documents  
Learned something again...
 
Turbo46

Guru

Joined: 24/12/2017
Location: Australia
Posts: 1120
Posted: 09:55pm 15 Nov 2022
Copy link to clipboard 
Print this post

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:
  Quote  T returns the id code of the Wii device: &HA4200000=Original,
&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
© JAQ Software 2022