diff --git a/examples/Any/DebugPrint/DebugPrint.ino b/examples/Any/DebugPrint/DebugPrint.ino index c03c9b2..2776d05 100644 --- a/examples/Any/DebugPrint/DebugPrint.ino +++ b/examples/Any/DebugPrint/DebugPrint.ino @@ -26,7 +26,7 @@ #include -ExtensionController controller; +ExtensionPort controller; void setup() { Serial.begin(115200); diff --git a/examples/Any/IdentifyController/IdentifyController.ino b/examples/Any/IdentifyController/IdentifyController.ino index 36fce84..f68d729 100644 --- a/examples/Any/IdentifyController/IdentifyController.ino +++ b/examples/Any/IdentifyController/IdentifyController.ino @@ -26,7 +26,7 @@ #include -ExtensionController controller; +ExtensionPort controller; void setup() { Serial.begin(115200); diff --git a/examples/Any/MultipleTypes/MultipleTypes.ino b/examples/Any/MultipleTypes/MultipleTypes.ino index e06b4b7..1e18ce0 100644 --- a/examples/Any/MultipleTypes/MultipleTypes.ino +++ b/examples/Any/MultipleTypes/MultipleTypes.ino @@ -26,26 +26,26 @@ #include -ExtensionController controller; // Port for communicating with extension controllers +ExtensionPort port; // Port for communicating with extension controllers -Nunchuk::Shared nchuk(controller); // Read Nunchuk formatted data from the port -ClassicController::Shared classic(controller); // Read Classic Controller formatted data from the port +Nunchuk::Shared nchuk(port); // Read Nunchuk formatted data from the port +ClassicController::Shared classic(port); // Read Classic Controller formatted data from the port void setup() { Serial.begin(115200); - controller.begin(); + port.begin(); - while (!controller.connect()) { + while (!port.connect()) { Serial.println("No controller found!"); delay(1000); } } void loop() { - boolean success = controller.update(); // Get new data from the controller + boolean success = port.update(); // Get new data from the controller if (success == true) { // We've got data! - ExtensionType conType = controller.getControllerType(); + ExtensionType conType = port.getControllerType(); switch (conType) { case(ExtensionType::Nunchuk): diff --git a/examples/Any/SpeedTest/SpeedTest.ino b/examples/Any/SpeedTest/SpeedTest.ino index a3c2588..5321e13 100644 --- a/examples/Any/SpeedTest/SpeedTest.ino +++ b/examples/Any/SpeedTest/SpeedTest.ino @@ -26,7 +26,7 @@ #include -ExtensionController controller; // Generic controller, 6 bytes +ExtensionPort controller; // Generic controller port, 6 bytes const long TestDuration = 1000; // Length of each test, in milliseconds diff --git a/extras/AddingControllers.md b/extras/AddingControllers.md index 8c9ea2e..14e0f65 100644 --- a/extras/AddingControllers.md +++ b/extras/AddingControllers.md @@ -4,7 +4,7 @@ If you want to use an extension controller that is not currently supported by th ## Step #1: Creating The Class Framework The first step in adding support for your controller is building it a class. The header (.h) and implementation (.cpp) files live within the `controllers` folder in the source directory. You'll need to create both of these files with the name of your controller. -Controller classes live inside the library namespace and inherit from the `ExtensionPort` class, which contains methods for communicating with the controllers and manipulating the control surface data. This includes combining multi-byte data and extracting bits that correspond to button presses. To use this you'll need to include the "ExtensionController.h" header, which is in the `internal` source directory. +Controller classes live inside the library namespace and inherit from the `ExtensionController` class, which contains methods for communicating with the controllers and manipulating the control surface data. This includes combining multi-byte data and extracting bits that correspond to button presses. To use this you'll need to include the "ExtensionController.h" header, which is in the `internal` source directory. The class name for your controller is going to be the "Shared" version of the class, which uses a reference to port and control data that exists elsewhere - thus it has a `_Shared` suffix. Here is what the start of the `ClassicController_Shared` class looks like: @@ -12,16 +12,16 @@ The class name for your controller is going to be the "Shared" version of the cl #include "internal/ExtensionController.h" namespace NintendoExtensionCtrl { - class ClassicController_Shared : public ExtensionPort { + class ClassicController_Shared : public ExtensionController { public: ClassicController_Shared(ExtensionData &dataRef) : - ExtensionPort(dataRef, ExtensionType::ClassicController) {} + ExtensionController(dataRef, ExtensionType::ClassicController) {} - ClassicController_Shared(ExtensionController &controller) : + ClassicController_Shared(ExtensionPort &controller) : ClassicController_Shared(controller.getExtensionData()) {} ``` -Note how the constructors use a reference to an `ExtensionData` class *external* to the controller class itself. You can also see that the controller's identity is passed to the `ExtensionPort` class to limit what types of controllers can connect (more on that in a bit). +Note how the constructors use a reference to an `ExtensionData` class *external* to the controller class itself. You can also see that the controller's identity is passed to the `ExtensionController` class to limit what types of controllers can connect (more on that in a bit). ## Step #2: Building Your Data Maps The next step is to add the data maps for your controller. These define where the data for each control input lies within in the data array. @@ -72,7 +72,7 @@ The resulting bit from the control data is extracted and inverted, as extension ```C++ BitMap ButtonA = { 5, 4 }; ``` -Full definitions of these data types can be found in the [`NXC_DataMaps.h`](../src/internal/NXC_DataMaps.h) file. Methods for using them are defined in the `ExtensionPort` class definition ([`ExtensionController.h`](../src/internal/ExtensionController.h)). +Full definitions of these data types can be found in the [`NXC_DataMaps.h`](../src/internal/NXC_DataMaps.h) file. Methods for using them are defined in the `ExtensionController` class definition ([`ExtensionController.h`](../src/internal/ExtensionController.h)). --- @@ -159,13 +159,13 @@ Once that's done, head back to your controller's header file and add that identi ``` ClassicController_Shared(ExtensionData &dataRef) : - ExtensionPort(dataRef, ExtensionType::ClassicController) {} + ExtensionController(dataRef, ExtensionType::ClassicController) {} ``` You will also need to edit the switch statement in the `IdentifyControllers` example to add your controller to the 'switch' statement. ## Step #6: Create the Combined Class -The last step to get your controller working is to create a combined class that inherits from your `_Shared` class and bundles it with a set of extension port data to use. This creates an easy to use class for most users who are looking to get data from just one controller. Just copy this line, replacing all instances of `YourController` with your controller's name: +The last step to get your controller working is to create a combined class that inherits from your `_Shared` class and bundles it with a set of extension data to use. This creates an easy to use class for most users who are looking to get data from just one controller. Just copy this line, replacing all instances of `YourController` with your controller's name: ```C++ using YourController = NintendoExtensionCtrl::BuildControllerClass diff --git a/src/controllers/ClassicController.h b/src/controllers/ClassicController.h index ce56b74..3c3ab2e 100644 --- a/src/controllers/ClassicController.h +++ b/src/controllers/ClassicController.h @@ -26,7 +26,7 @@ #include "internal/ExtensionController.h" namespace NintendoExtensionCtrl { - class ClassicController_Shared : public ExtensionPort { + class ClassicController_Shared : public ExtensionController { public: struct Maps { constexpr static ByteMap LeftJoyX = ByteMap(0, 6, 0, 0); @@ -59,10 +59,10 @@ namespace NintendoExtensionCtrl { }; ClassicController_Shared(ExtensionData &dataRef) : - ExtensionPort(dataRef, ExtensionType::ClassicController) {} + ExtensionController(dataRef, ExtensionType::ClassicController) {} - ClassicController_Shared(ExtensionController &controller) : - ClassicController_Shared(controller.getExtensionData()) {} + ClassicController_Shared(ExtensionPort &port) : + ClassicController_Shared(port.getExtensionData()) {} uint8_t leftJoyX() const; // 6 bits, 0-63 uint8_t leftJoyY() const; diff --git a/src/controllers/DJTurntable.h b/src/controllers/DJTurntable.h index 780e862..eed7dfa 100644 --- a/src/controllers/DJTurntable.h +++ b/src/controllers/DJTurntable.h @@ -28,7 +28,7 @@ #include "ClassicController.h" // For joystick and +/- control maps namespace NintendoExtensionCtrl { - class DJTurntableController_Shared : public ExtensionPort { + class DJTurntableController_Shared : public ExtensionController { public: struct Maps { constexpr static ByteMap JoyX = ClassicController_Shared::Maps::LeftJoyX; @@ -56,10 +56,10 @@ namespace NintendoExtensionCtrl { }; DJTurntableController_Shared(ExtensionData& dataRef) : - ExtensionPort(dataRef, ExtensionType::DJTurntableController), left(*this), right(*this) {} + ExtensionController(dataRef, ExtensionType::DJTurntableController), left(*this), right(*this) {} - DJTurntableController_Shared(ExtensionController &controller) : - DJTurntableController_Shared(controller.getExtensionData()) {} + DJTurntableController_Shared(ExtensionPort &port) : + DJTurntableController_Shared(port.getExtensionData()) {} enum class TurntableConfig { BaseOnly, diff --git a/src/controllers/DrumController.h b/src/controllers/DrumController.h index 47814d7..eb736e3 100644 --- a/src/controllers/DrumController.h +++ b/src/controllers/DrumController.h @@ -28,7 +28,7 @@ #include "ClassicController.h" // For joystick and +/- control maps namespace NintendoExtensionCtrl { - class DrumController_Shared : public ExtensionPort { + class DrumController_Shared : public ExtensionController { public: struct Maps { constexpr static ByteMap JoyX = ClassicController_Shared::Maps::LeftJoyX; @@ -52,10 +52,10 @@ namespace NintendoExtensionCtrl { }; DrumController_Shared(ExtensionData &dataRef) : - ExtensionPort(dataRef, ExtensionType::DrumController) {} + ExtensionController(dataRef, ExtensionType::DrumController) {} - DrumController_Shared(ExtensionController &controller) : - DrumController_Shared(controller.getExtensionData()) {} + DrumController_Shared(ExtensionPort &port) : + DrumController_Shared(port.getExtensionData()) {} enum VelocityID : uint8_t { None = 0x1F, diff --git a/src/controllers/GuitarController.h b/src/controllers/GuitarController.h index deba775..4ad2663 100644 --- a/src/controllers/GuitarController.h +++ b/src/controllers/GuitarController.h @@ -28,7 +28,7 @@ #include "ClassicController.h" // For joystick and +/- control maps namespace NintendoExtensionCtrl { - class GuitarController_Shared : public ExtensionPort { + class GuitarController_Shared : public ExtensionController { public: struct Maps { constexpr static ByteMap JoyX = ClassicController_Shared::Maps::LeftJoyX; @@ -51,10 +51,10 @@ namespace NintendoExtensionCtrl { }; GuitarController_Shared(ExtensionData &dataRef) : - ExtensionPort(dataRef, ExtensionType::GuitarController) {} + ExtensionController(dataRef, ExtensionType::GuitarController) {} - GuitarController_Shared(ExtensionController &controller) : - GuitarController_Shared(controller.getExtensionData()) {} + GuitarController_Shared(ExtensionPort &port) : + GuitarController_Shared(port.getExtensionData()) {} uint8_t joyX() const; // 6 bits, 0-63 uint8_t joyY() const; diff --git a/src/controllers/Nunchuk.h b/src/controllers/Nunchuk.h index 189b662..a3d95bc 100644 --- a/src/controllers/Nunchuk.h +++ b/src/controllers/Nunchuk.h @@ -26,7 +26,7 @@ #include "internal/ExtensionController.h" namespace NintendoExtensionCtrl { - class Nunchuk_Shared : public ExtensionPort { + class Nunchuk_Shared : public ExtensionController { public: struct Maps { constexpr static CtrlIndex JoyX = 0; @@ -46,10 +46,10 @@ namespace NintendoExtensionCtrl { }; Nunchuk_Shared(ExtensionData &dataRef) : - ExtensionPort(dataRef, ExtensionType::Nunchuk) {} + ExtensionController(dataRef, ExtensionType::Nunchuk) {} - Nunchuk_Shared(ExtensionController &controller) : - Nunchuk_Shared(controller.getExtensionData()) {} + Nunchuk_Shared(ExtensionPort &port) : + Nunchuk_Shared(port.getExtensionData()) {} uint8_t joyX() const; // 8 bits, 0-255 uint8_t joyY() const; diff --git a/src/internal/ExtensionController.cpp b/src/internal/ExtensionController.cpp index 9ff7c29..c9384ea 100644 --- a/src/internal/ExtensionController.cpp +++ b/src/internal/ExtensionController.cpp @@ -22,24 +22,24 @@ #include "ExtensionController.h" -namespace NintendoExtensionCtrl { +using namespace NintendoExtensionCtrl; -ExtensionPort::ExtensionPort(ExtensionData& dataRef) - : ExtensionPort(dataRef, ExtensionType::AnyController) {} +ExtensionController::ExtensionController(ExtensionData& dataRef) + : ExtensionController(dataRef, ExtensionType::AnyController) {} -ExtensionPort::ExtensionPort(ExtensionData& dataRef, ExtensionType conID) +ExtensionController::ExtensionController(ExtensionData& dataRef, ExtensionType conID) : i2c(dataRef.i2c), id(conID), data(dataRef) {} -void ExtensionPort::begin() { +void ExtensionController::begin() { data.i2c.begin(); // Initialize the bus } -boolean ExtensionPort::connect() { +boolean ExtensionController::connect() { disconnect(); // Clear current data return reconnect(); } -boolean ExtensionPort::reconnect() { +boolean ExtensionController::reconnect() { boolean success = false; if (initialize(data.i2c)) { @@ -53,21 +53,21 @@ boolean ExtensionPort::reconnect() { return success; } -void ExtensionPort::disconnect() { +void ExtensionController::disconnect() { data.connectedType = ExtensionType::NoController; // Nothing connected memset(&data.controlData, 0x00, ExtensionData::ControlDataSize); // Clear control data } -void ExtensionPort::reset() { +void ExtensionController::reset() { disconnect(); requestSize = MinRequestSize; // Request size back to minimum } -void ExtensionPort::identifyController() { +void ExtensionController::identifyController() { data.connectedType = NintendoExtensionCtrl::identifyController(data.i2c); // Polls the controller for its identity } -boolean ExtensionPort::controllerIDMatches() const { +boolean ExtensionController::controllerIDMatches() const { if (data.connectedType == id) { return true; // Match! } @@ -78,11 +78,11 @@ boolean ExtensionPort::controllerIDMatches() const { return false; // Enforced types or no controller connected } -ExtensionType ExtensionPort::getControllerType() const { +ExtensionType ExtensionController::getControllerType() const { return data.connectedType; } -boolean ExtensionPort::update() { +boolean ExtensionController::update() { if (controllerIDMatches() && requestControlData(data.i2c, requestSize, data.controlData)) { return verifyData(data.controlData, requestSize); } @@ -90,29 +90,29 @@ boolean ExtensionPort::update() { return false; // Something went wrong :( } -uint8_t ExtensionPort::getControlData(uint8_t controlIndex) const { +uint8_t ExtensionController::getControlData(uint8_t controlIndex) const { return data.controlData[controlIndex]; } -void ExtensionPort::setControlData(uint8_t index, uint8_t val) { +void ExtensionController::setControlData(uint8_t index, uint8_t val) { data.controlData[index] = val; } -ExtensionData & ExtensionPort::getExtensionData() const { +ExtensionController::ExtensionData & ExtensionController::getExtensionData() const { return data; } -void ExtensionPort::setRequestSize(size_t r) { +void ExtensionController::setRequestSize(size_t r) { if (r >= MinRequestSize && r <= MaxRequestSize) { requestSize = (uint8_t) r; } } -void ExtensionPort::printDebug(Print& output) const { +void ExtensionController::printDebug(Print& output) const { printDebugRaw(output); } -void ExtensionPort::printDebugID(Print& output) const { +void ExtensionController::printDebugID(Print& output) const { uint8_t idData[ID_Size]; boolean success = requestIdentity(data.i2c, idData); @@ -125,15 +125,13 @@ void ExtensionPort::printDebugID(Print& output) const { } } -void ExtensionPort::printDebugRaw(Print& output) const { +void ExtensionController::printDebugRaw(Print& output) const { printDebugRaw(HEX, output); } -void ExtensionPort::printDebugRaw(uint8_t baseFormat, Print& output) const { +void ExtensionController::printDebugRaw(uint8_t baseFormat, Print& output) const { output.print("Raw["); output.print(requestSize); output.print("]: "); printRaw(data.controlData, requestSize, baseFormat, output); } - -} // End "NintendoExtensionCtrl" namespace diff --git a/src/internal/ExtensionController.h b/src/internal/ExtensionController.h index 7e9f7e6..653e3b3 100644 --- a/src/internal/ExtensionController.h +++ b/src/internal/ExtensionController.h @@ -28,10 +28,11 @@ #include "NXC_Utils.h" #include "NXC_DataMaps.h" -namespace NintendoExtensionCtrl { - class ExtensionData { - friend class ExtensionPort; - public: +class ExtensionController { +public: + struct ExtensionData { + friend class ExtensionController; + ExtensionData(NXC_I2C_TYPE& i2cbus = NXC_I2C_DEFAULT) : i2c(i2cbus) {} @@ -43,71 +44,74 @@ namespace NintendoExtensionCtrl { uint8_t controlData[ControlDataSize]; }; - class ExtensionPort { - public: - ExtensionPort(ExtensionData& dataRef); + ExtensionController(ExtensionData& dataRef); - void begin(); + void begin(); - boolean connect(); - boolean reconnect(); + boolean connect(); + boolean reconnect(); - boolean update(); + boolean update(); - void reset(); + void reset(); - ExtensionType getControllerType() const; - uint8_t getControlData(uint8_t controlIndex) const; - ExtensionData & getExtensionData() const; + ExtensionType getControllerType() const; + uint8_t getControlData(uint8_t controlIndex) const; + ExtensionData & getExtensionData() const; - void setRequestSize(size_t size = MinRequestSize); + void setRequestSize(size_t size = MinRequestSize); - void printDebug(Print& output = NXC_SERIAL_DEFAULT) const; - void printDebugID(Print& output = NXC_SERIAL_DEFAULT) const; - void printDebugRaw(Print& output = NXC_SERIAL_DEFAULT) const; - void printDebugRaw(uint8_t baseFormat, Print& output = NXC_SERIAL_DEFAULT) const; + void printDebug(Print& output = NXC_SERIAL_DEFAULT) const; + void printDebugID(Print& output = NXC_SERIAL_DEFAULT) const; + void printDebugRaw(Print& output = NXC_SERIAL_DEFAULT) const; + void printDebugRaw(uint8_t baseFormat, Print& output = NXC_SERIAL_DEFAULT) const; - static const uint8_t MinRequestSize = 6; // Smallest reporting mode (0x37) - static const uint8_t MaxRequestSize = ExtensionData::ControlDataSize; + static const uint8_t MinRequestSize = 6; // Smallest reporting mode (0x37) + static const uint8_t MaxRequestSize = ExtensionData::ControlDataSize; - NXC_I2C_TYPE & i2c; // Easily accessible I2C reference - const ExtensionType id = ExtensionType::AnyController; + NXC_I2C_TYPE & i2c; // Easily accessible I2C reference + const ExtensionType id = ExtensionType::AnyController; - protected: - ExtensionPort(ExtensionData& dataRef, ExtensionType conID); +protected: + ExtensionController(ExtensionData& dataRef, ExtensionType conID); - uint8_t getControlData(const ByteMap map) const { - return (data.controlData[map.index] & map.mask) >> map.offset; - } + typedef NintendoExtensionCtrl::CtrlIndex CtrlIndex; + typedef NintendoExtensionCtrl::ByteMap ByteMap; + typedef NintendoExtensionCtrl::BitMap BitMap; - template - uint8_t getControlData(const ByteMap(&map)[size]) const { - uint8_t dataOut = 0x00; - for (size_t i = 0; i < size; i++) { - /* Repeated line from the single-ByteMap function above. Apparently the - constexpr stuff doesn't like being passed through nested functions. */ - dataOut |= (data.controlData[map[i].index] & map[i].mask) >> map[i].offset; - //dataOut |= getControlData(map[i]); - } - return dataOut; - } + uint8_t getControlData(const ByteMap map) const { + return (data.controlData[map.index] & map.mask) >> map.offset; + } - boolean getControlBit(const BitMap map) const { - return !(data.controlData[map.index] & (1 << map.position)); // Inverted logic, '0' is pressed + template + uint8_t getControlData(const ByteMap(&map)[size]) const { + uint8_t dataOut = 0x00; + for (size_t i = 0; i < size; i++) { + /* Repeated line from the single-ByteMap function above. Apparently the + constexpr stuff doesn't like being passed through nested functions. */ + dataOut |= (data.controlData[map[i].index] & map[i].mask) >> map[i].offset; + //dataOut |= getControlData(map[i]); } + return dataOut; + } - void setControlData(uint8_t index, uint8_t val); + boolean getControlBit(const BitMap map) const { + return !(data.controlData[map.index] & (1 << map.position)); // Inverted logic, '0' is pressed + } - private: - ExtensionData &data; // I2C and control data storage + void setControlData(uint8_t index, uint8_t val); - void disconnect(); - void identifyController(); - boolean controllerIDMatches() const; +private: + ExtensionData &data; // I2C and control data storage - uint8_t requestSize = MinRequestSize; - }; + void disconnect(); + void identifyController(); + boolean controllerIDMatches() const; + uint8_t requestSize = MinRequestSize; +}; + +namespace NintendoExtensionCtrl { template class BuildControllerClass : public ControllerMap { public: @@ -124,14 +128,13 @@ namespace NintendoExtensionCtrl { // * Control data array // This data can be shared between controller instances using a single // logical endpoint to keep memory down. - ExtensionData portData; + ExtensionController::ExtensionData portData; }; } // Public-facing version of the extension 'port' class that combines the -// communication (ExtensionPort) with a data instance (ExtensionData), but omits +// communication (ExtensionController) with a data instance (ExtensionData), but omits // any controller-specific data maps. -using ExtensionController = NintendoExtensionCtrl::BuildControllerClass - ; +using ExtensionPort = NintendoExtensionCtrl::BuildControllerClass; #endif