This commit is contained in:
gorbit99
2025-12-14 17:15:13 +01:00
parent f2f3ea18cf
commit 4061db4953
11 changed files with 318 additions and 21 deletions

View File

@@ -1,37 +1,37 @@
/*
SlimeVR Code is placed under the MIT license
Copyright (c) 2024 Eiren Rain & SlimeVR contributors
SlimeVR Code is placed under the MIT license
Copyright (c) 2024 Eiren Rain & SlimeVR contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include <cstdint>
#include <string>
class PinInterface
{
class PinInterface {
public:
virtual bool init() { return true; };
virtual int digitalRead() = 0;
virtual void pinMode(uint8_t mode) = 0;
virtual void digitalWrite(uint8_t val) = 0;
virtual float analogRead() = 0;
[[nodiscard]] virtual std::string toString() const = 0;
};

View File

@@ -26,4 +26,6 @@ int DirectPinInterface::digitalRead() { return ::digitalRead(_pinNum); }
void DirectPinInterface::pinMode(uint8_t mode) { ::pinMode(_pinNum, mode); }
void DirectPinInterface::digitalWrite(uint8_t val) { ::digitalWrite(_pinNum, val); }
void DirectPinInterface::digitalWrite(uint8_t val) { ::digitalWrite(_pinNum, val); }
float DirectPinInterface::analogRead() { return ::analogRead(_pinNum); }

View File

@@ -38,6 +38,7 @@ public:
int digitalRead() override final;
void pinMode(uint8_t mode) override final;
void digitalWrite(uint8_t val) override final;
float analogRead() override final;
[[nodiscard]] std::string toString() const final {
using namespace std::string_literals;

View File

@@ -28,4 +28,6 @@ void MCP23X17PinInterface::pinMode(uint8_t mode) { _mcp23x17->pinMode(_pinNum, m
void MCP23X17PinInterface::digitalWrite(uint8_t val) {
_mcp23x17->digitalWrite(_pinNum, val);
}
}
float MCP23X17PinInterface::analogRead() { return digitalRead() ? 1.0f : 0.0f; }

View File

@@ -55,6 +55,7 @@ public:
int digitalRead() override final;
void pinMode(uint8_t mode) override final;
void digitalWrite(uint8_t val) override final;
float analogRead() override final;
[[nodiscard]] std::string toString() const final {
using namespace std::string_literals;

View File

@@ -0,0 +1,115 @@
/*
SlimeVR Code is placed under the MIT license
Copyright (c) 2025 Gorbit99 & SlimeVR Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <Arduino.h>
#include <cassert>
#include "ParallelMuxInterface.h"
namespace SlimeVR {
ParallelMuxInterface::ParallelMuxInterface(
PinInterface* dataPin,
std::vector<PinInterface*>& addressPins,
PinInterface* enablePin,
bool enableActiveLevel,
bool addressActiveLevel
)
: dataPin{dataPin}
, addressPins{addressPins}
, enablePin{enablePin}
, enableActiveLevel{enableActiveLevel}
, addressActiveLevel{addressActiveLevel} {
assert(addressPins.size() <= 8);
}
bool ParallelMuxInterface::init() {
if (enablePin != nullptr) {
enablePin->pinMode(OUTPUT);
enablePin->digitalWrite(enableActiveLevel);
}
for (auto* pin : addressPins) {
pin->pinMode(OUTPUT);
pin->digitalWrite(false);
}
return true;
}
void ParallelMuxInterface::pinMode(uint8_t mode) { dataPin->pinMode(mode); }
void ParallelMuxInterface::digitalWrite(uint8_t address, uint8_t value) {
switchTo(address);
dataPin->digitalWrite(value);
}
int ParallelMuxInterface::digitalRead(uint8_t address) {
switchTo(address);
return dataPin->digitalRead();
}
float ParallelMuxInterface::analogRead(uint8_t address) {
switchTo(address);
return dataPin->analogRead();
}
void ParallelMuxInterface::switchTo(uint8_t address) {
assert(address < 1 << addressPins.size());
if (address == currentAddress) {
return;
}
if (enablePin != nullptr) {
enablePin->digitalWrite(!enableActiveLevel);
}
for (auto* addressPin : addressPins) {
bool value = address & 0x01;
address >>= 1;
addressPin->digitalWrite(value);
}
if (enablePin != nullptr) {
enablePin->digitalWrite(enableActiveLevel);
}
currentAddress = address;
delay(1);
}
std::string ParallelMuxInterface::toString() const {
std::string result = "Mux({";
for (size_t i = 0; i < addressPins.size(); i++) {
if (i != 0) {
result += ", ";
}
result += addressPins[i]->toString();
}
result += "}, ";
result += dataPin->toString();
result += ")";
return result;
}
} // namespace SlimeVR

View File

@@ -0,0 +1,59 @@
/*
SlimeVR Code is placed under the MIT license
Copyright (c) 2025 Gorbit99 & SlimeVR Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include <PinInterface.h>
#include <cstdint>
#include <vector>
namespace SlimeVR {
class ParallelMuxInterface {
public:
ParallelMuxInterface(
PinInterface* dataPin,
std::vector<PinInterface*>& addressPins,
PinInterface* enablePin = nullptr,
bool enableActiveLevel = false,
bool addressActiveLevel = true
);
bool init();
void pinMode(uint8_t mode);
void digitalWrite(uint8_t address, uint8_t value);
int digitalRead(uint8_t address);
float analogRead(uint8_t address);
[[nodiscard]] std::string toString() const;
private:
void switchTo(uint8_t address);
PinInterface* const dataPin;
const std::vector<PinInterface*> addressPins;
PinInterface* const enablePin = nullptr;
const bool enableActiveLevel = false;
const bool addressActiveLevel = true;
uint8_t currentAddress = 0;
};
} // namespace SlimeVR

View File

@@ -0,0 +1,40 @@
/*
SlimeVR Code is placed under the MIT license
Copyright (c) 2025 Gorbit99 & SlimeVR Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <string>
#include "ParallelMuxPin.h"
namespace SlimeVR {
ParallelMuxPin::ParallelMuxPin(ParallelMuxInterface* mux, uint8_t address)
: mux{mux}
, address{address} {}
void ParallelMuxPin::pinMode(uint8_t mode) { mux->pinMode(mode); }
void ParallelMuxPin::digitalWrite(uint8_t value) { mux->digitalWrite(address, value); }
int ParallelMuxPin::digitalRead() { return mux->digitalRead(address); }
float ParallelMuxPin::analogRead() { return mux->analogRead(address); }
std::string ParallelMuxPin::toString() const {
return "MuxPin(" + mux->toString() + ", " + std::to_string(address) + ")";
}
} // namespace SlimeVR

View File

@@ -0,0 +1,45 @@
/*
SlimeVR Code is placed under the MIT license
Copyright (c) 2025 Gorbit99 & SlimeVR Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#pragma once
#include <cstdint>
#include "ParallelMuxInterface.h"
#include "PinInterface.h"
namespace SlimeVR {
class ParallelMuxPin : public PinInterface {
public:
ParallelMuxPin(ParallelMuxInterface* mux, uint8_t address);
void pinMode(uint8_t mode) final;
void digitalWrite(uint8_t value) final;
int digitalRead() final;
float analogRead() final;
[[nodiscard]] std::string toString() const final;
private:
ParallelMuxInterface* const mux;
uint8_t address;
};
} // namespace SlimeVR

View File

@@ -34,6 +34,8 @@
#include "I2CPCAInterface.h"
#include "I2CWireSensorInterface.h"
#include "MCP23X17PinInterface.h"
#include "ParallelMuxInterface.h"
#include "ParallelMuxPin.h"
#include "SPIImpl.h"
#include "SensorInterface.h"
#include "i2cimpl.h"
@@ -97,6 +99,8 @@ public:
inline auto& i2cImpl() { return i2cImpls; }
inline auto& directSPIInterface() { return directSPIInterfaces; }
inline auto& spiImpl() { return spiImpls; }
inline auto& parallelMuxInterface() { return parallelMuxInterfaces; }
inline auto& parallelMuxPinInterface() { return parallelMuxPinInterfaces; }
private:
SensorInterface<DirectPinInterface, int> directPinInterfaces{[](int pin) {
@@ -108,6 +112,16 @@ private:
SensorInterface<Sensors::I2CImpl, uint8_t> i2cImpls;
SensorInterface<DirectSPIInterface, SPIClass, SPISettings> directSPIInterfaces;
SensorInterface<Sensors::SPIImpl, DirectSPIInterface*, PinInterface*> spiImpls;
SensorInterface<
ParallelMuxInterface,
PinInterface*,
std::vector<PinInterface*>,
PinInterface*,
bool,
bool>
parallelMuxInterfaces;
SensorInterface<ParallelMuxPin, ParallelMuxInterface*, uint8_t>
parallelMuxPinInterfaces;
};
} // namespace SlimeVR

View File

@@ -60,6 +60,24 @@ uint8_t SensorBuilder::buildAllSensors() {
SPISettings(clockFreq, bitOrder, dataMode)
);
};
[[maybe_unused]] static auto MUX_PIN
= [&](PinInterface* data,
std::vector<PinInterface*>&& addressPins,
uint8_t channel,
PinInterface* enablePin = nullptr,
bool enableActiveLevel = false,
bool addressActiveLevel = true) constexpr {
return interfaceManager.parallelMuxPinInterface().get(
interfaceManager.parallelMuxInterface().get(
data,
addressPins,
enablePin,
enableActiveLevel,
addressActiveLevel
),
channel
);
};
// Apply descriptor list and expand to entries
SENSOR_DESC_LIST