
' Controllers
' initial support for:
' digital joystick only
' single joystick only
' direct switch-pin connection on

' untested:
' support one joystick or dpad on wii controller

' future plans:
' support analog joystick
' support analog joystick for game treated as dpad / digital joystick
' support paddle
' support 2 controllers.

' Pins for direct switch 

CONST Pins.Up = 35 ' digital up - pin 35
CONST Pins.Down = 36 ' digital down - pin 36
CONST Pins.Left = 38 ' digital left - pin 38
CONST Pins.Right = 29 ' digital right - pin 29

CONST Pins.ButtonA = 32 ' Button A - pin 32
CONST Pins.ButtonB = 33 ' Button B - pin 33

CONST Controllers.Type.Nunchuk = 10
CONST Controllers.Type.Classic = 11
CONST Controllers.Type.DigitalPins = 12

'Types not supported yet:
CONST Controllers.Type.ClassicPro = 1234

'Other types to check later:
'SNES classic controller? NES classic controller?

DIM Controllers.Type

DIM Analog.X.LowThreshold=64
DIM Analog.Y.LowThreshold=64

DIM Analog.X.HighThreshold=192
DIM Analog.Y.HighThreshold=192

SUB Pins.InitDigital p
  ' Set pin number p as digital input, with pullup.
  SetPin p, din, pullup
END SUB


CONST wii.id.nunchuk = &HA4200000
CONST wii.id.classic = &HA4200101
CONST wii.id.balance = &HA4200402

'Saw this one on another site - not sure if it's needed:
CONST wii.id.classicpro = &H100A4200402


''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Controllers subs and functions for all supported controllers '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

SUB Controllers.Autodetect

  ' Default if no wii controller detected
  Controllers.Type=Controllers.Type.DigitalPins

  ON ERROR SKIP
  Wii nunchuk open
  if mm.errno <> 0 then
    ' "No Wii controller detected"
  else
    LOCAL FrontPort=3
    LOCAL t_id = nunchuk(T,FrontPort)
    'print "Wii controller detected"
    'print "ID: ";Hex(t_if)
    SELECT CASE t_id
      CASE wii.id.nunchuk
        'print "nunchuk detected"
        Controllers.Type=Controllers.Type.Nunchuk
      CASE wii.id.classic
        'print "classic controller detected"
        Controllers.Type=Controllers.Type.Classic
    END SELECT
    wii nunchuk close
  end if
END SUB

SUB Controllers.Init players, ctype
  ' default argument for players is interpreted as 1 player

  if players > 1 then print "multiple players not supported yet"

  if ctype=0 then
    Controllers.Autodetect
  else
    Controllers.Type=ctype
  endif

  SELECT CASE Controllers.Type
    CASE Controllers.Type.DigitalPins
      ReadPins.Init players, ctype

    CASE Controllers.Type.Classic
      Wii classic open

    CASE Controllers.Type.Nunchuk
      Wii nunchuk open
      'could set analog thresholds here based on calibration but
      'not vital probably

    CASE ELSE
      print "unknown controller type"
  END SELECT
END SUB

FUNCTION Controllers.Up()
  SELECT CASE Controllers.Type
    CASE Controllers.Type.DigitalPins
      Controllers.Up = ReadPins.Up()
    CASE Controllers.Type.Classic
      Controllers.Up = Classic.Up()
    CASE Controllers.Type.Nunchuk
      Controllers.Up = Nunchuk.Up()
  END SELECT
END FUNCTION

FUNCTION Controllers.Down()
  SELECT CASE Controllers.Type
    CASE Controllers.Type.DigitalPins
      Controllers.Down = ReadPins.Down()
    CASE Controllers.Type.Classic
      Controllers.Down = Classic.Down()
    CASE Controllers.Type.Nunchuk
      Controllers.Down = Nunchuk.Down()
  END SELECT
END FUNCTION

FUNCTION Controllers.Left()
  SELECT CASE Controllers.Type
    CASE Controllers.Type.DigitalPins
      Controllers.Left = ReadPins.Left()
    CASE Controllers.Type.Classic
      Controllers.Left = Classic.Left()
    CASE Controllers.Type.Nunchuk
      Controllers.Left = Nunchuk.Left()
  END SELECT
END FUNCTION

FUNCTION Controllers.Right()
  SELECT CASE Controllers.Type
    CASE Controllers.Type.DigitalPins
      Controllers.Right = ReadPins.Right()
    CASE Controllers.Type.Classic
      Controllers.Right = Classic.Right()
    CASE Controllers.Type.Nunchuk
      Controllers.Right = Nunchuk.Right()
  END SELECT
END FUNCTION

FUNCTION Controllers.ButtonA()
  SELECT CASE Controllers.Type
    CASE Controllers.Type.DigitalPins
      Controllers.ButtonA = ReadPins.ButtonA()
    CASE Controllers.Type.Classic
      Controllers.ButtonA = Classic.ButtonA()
    CASE Controllers.Type.Nunchuk
      Controllers.ButtonA = Nunchuk.ButtonA()
  END SELECT
END FUNCTION

FUNCTION Controllers.ButtonB()
  SELECT CASE Controllers.Type
    CASE Controllers.Type.DigitalPins
      Controllers.ButtonB = ReadPins.ButtonB()
    CASE Controllers.Type.Classic
      Controllers.ButtonB = Classic.ButtonB()
    CASE Controllers.Type.Nunchuk
      Controllers.ButtonB = Nunchuk.ButtonB()
  END SELECT
END FUNCTION


'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ReadPins subs and functions for directly connected digital switch joysticks '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

SUB ReadPins.Init players, ctype
  Pins.InitDigital Pins.Up
  Pins.InitDigital Pins.Down
  Pins.InitDigital Pins.Left
  Pins.InitDigital Pins.Right
  Pins.InitDigital Pins.ButtonA
  Pins.InitDigital Pins.ButtonB
END SUB

FUNCTION ReadPins.Up()
  ' Pins are low (0) for active
  ReadPins.Up = pin(Pins.Up) = 0
END FUNCTION

FUNCTION ReadPins.Down()
  ' Pins are low (0) for active
  ReadPins.Down = pin(Pins.Down) = 0
END FUNCTION

FUNCTION ReadPins.Left()
  ' Pins are low (0) for active
  ReadPins.Left = pin(Pins.Left) = 0
END FUNCTION

FUNCTION ReadPins.Right()
  ' Pins are low (0) for active
  ReadPins.Right = pin(Pins.Right) = 0
END FUNCTION

FUNCTION ReadPins.ButtonA()
  ' Pins are low (0) for active
  ReadPins.ButtonA = pin(Pins.ButtonA) = 0
END FUNCTION

FUNCTION ReadPins.ButtonB()
  ' Pins are low (0) for active
  ReadPins.ButtonB = pin(Pins.ButtonB) = 0
END FUNCTION



'''''''''''''''''''''''''''''''''''''''''''''''''''''
' Nunchuk subs and functions for nunchuk controller '
'''''''''''''''''''''''''''''''''''''''''''''''''''''

'SUB Nunchuk.Init players, ctype
'END SUB

FUNCTION Nunchuk.Up()
  Nunchuk.Up = nunchuk(JY) > Analog.Y.HighThreshold
END FUNCTION

FUNCTION Nunchuk.Down()
  Nunchuk.Down = nunchuk(JY) < Analog.Y.LowThreshold
END FUNCTION

FUNCTION Nunchuk.Left()
  Nunchuk.Left = nunchuk(JX) < Analog.X.LowThreshold
END FUNCTION

FUNCTION Nunchuk.Right()
  Nunchuk.Right = nunchuk(JX) > Analog.X.HighThreshold
END FUNCTION

FUNCTION Nunchuk.ButtonA()
  Nunchuk.ButtonA = nunchuk(C)
END FUNCTION

FUNCTION Nunchuk.ButtonB()
  Nunchuk.ButtonB = nunchuk(Z)
END FUNCTION

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Classic subs and functions for dpad on classic controller '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'SUB Classic.Init players, ctype
'END SUB


FUNCTION Classic.ReadBit(BitNumber)
 'CONST fake_classic_b = 256
 'Classic.ReadBit = (fake_classic_b AND (1<<BitNumber)) <> 0
  Classic.ReadBit = (Classic(B)     AND (1<<BitNumber)) <> 0
END FUNCTION

FUNCTION Classic.Up()
  Classic.Up = Classic.ReadBit(7)
END FUNCTION

FUNCTION Classic.Down()
  Classic.Down = Classic.ReadBit(5)
END FUNCTION

FUNCTION Classic.Left()
  Classic.Left = Classic.ReadBit(8)
END FUNCTION

FUNCTION Classic.Right()
  Classic.Right = Classic.ReadBit(6)
END FUNCTION

FUNCTION Classic.ButtonA()
  Classic.ButtonA = Classic.ReadBit(11)
END FUNCTION

FUNCTION Classic.ButtonB()
  Classic.ButtonB = Classic.ReadBit(13)
END FUNCTION


