DCC++: added accessory output support
Dieser Commit ist enthalten in:
Ursprung
86f9956622
Commit
22099e80f9
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2021 Reinder Feenstra
|
||||
* Copyright (C) 2021-2022 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -40,9 +40,11 @@ DCCPlusPlusInterface::DCCPlusPlusInterface(const std::weak_ptr<World>& world, st
|
||||
, flowControl{this, "flow_control", SerialFlowControl::None, PropertyFlags::ReadWrite | PropertyFlags::Store}
|
||||
, dccplusplus{this, "dccplusplus", nullptr, PropertyFlags::ReadOnly | PropertyFlags::Store | PropertyFlags::SubObject}
|
||||
, decoders{this, "decoders", nullptr, PropertyFlags::ReadOnly | PropertyFlags::NoStore | PropertyFlags::SubObject}
|
||||
, outputs{this, "outputs", nullptr, PropertyFlags::ReadOnly | PropertyFlags::NoStore | PropertyFlags::SubObject}
|
||||
{
|
||||
dccplusplus.setValueInternal(std::make_shared<DCCPlusPlus::Settings>(*this, dccplusplus.name()));
|
||||
decoders.setValueInternal(std::make_shared<DecoderList>(*this, decoders.name()));
|
||||
outputs.setValueInternal(std::make_shared<OutputList>(*this, outputs.name()));
|
||||
|
||||
Attributes::addDisplayName(device, DisplayName::Serial::device);
|
||||
Attributes::addEnabled(device, !online);
|
||||
@ -64,6 +66,9 @@ DCCPlusPlusInterface::DCCPlusPlusInterface(const std::weak_ptr<World>& world, st
|
||||
|
||||
Attributes::addDisplayName(decoders, DisplayName::Hardware::decoders);
|
||||
m_interfaceItems.insertBefore(decoders, notes);
|
||||
|
||||
Attributes::addDisplayName(outputs, DisplayName::Hardware::outputs);
|
||||
m_interfaceItems.insertBefore(outputs, notes);
|
||||
}
|
||||
|
||||
bool DCCPlusPlusInterface::addDecoder(Decoder& decoder)
|
||||
@ -88,6 +93,30 @@ void DCCPlusPlusInterface::decoderChanged(const Decoder& decoder, DecoderChangeF
|
||||
m_kernel->decoderChanged(decoder, changes, functionNumber);
|
||||
}
|
||||
|
||||
bool DCCPlusPlusInterface::addOutput(Output& output)
|
||||
{
|
||||
const bool success = OutputController::addOutput(output);
|
||||
if(success)
|
||||
outputs->addObject(output.shared_ptr<Output>());
|
||||
return success;
|
||||
}
|
||||
|
||||
bool DCCPlusPlusInterface::removeOutput(Output& output)
|
||||
{
|
||||
const bool success = OutputController::removeOutput(output);
|
||||
if(success)
|
||||
outputs->removeObject(output.shared_ptr<Output>());
|
||||
return success;
|
||||
}
|
||||
|
||||
bool DCCPlusPlusInterface::setOutputValue(uint32_t address, bool value)
|
||||
{
|
||||
return
|
||||
m_kernel &&
|
||||
inRange(address, outputAddressMinMax()) &&
|
||||
m_kernel->setOutput(static_cast<uint16_t>(address), value);
|
||||
}
|
||||
|
||||
bool DCCPlusPlusInterface::setOnline(bool& value)
|
||||
{
|
||||
if(!m_kernel && value)
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2021 Reinder Feenstra
|
||||
* Copyright (C) 2021-2022 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -28,6 +28,8 @@
|
||||
#include "../protocol/dccplusplus/settings.hpp"
|
||||
#include "../decoder/decodercontroller.hpp"
|
||||
#include "../decoder/decoderlist.hpp"
|
||||
#include "../output/outputcontroller.hpp"
|
||||
#include "../output/list/outputlist.hpp"
|
||||
#include "../../core/objectproperty.hpp"
|
||||
#include "../../enum/serialflowcontrol.hpp"
|
||||
|
||||
@ -37,6 +39,7 @@
|
||||
class DCCPlusPlusInterface final
|
||||
: public Interface
|
||||
, public DecoderController
|
||||
, public OutputController
|
||||
{
|
||||
CLASS_ID("interface.dccplusplus")
|
||||
CREATE(DCCPlusPlusInterface)
|
||||
@ -65,6 +68,7 @@ class DCCPlusPlusInterface final
|
||||
Property<SerialFlowControl> flowControl;
|
||||
ObjectProperty<DCCPlusPlus::Settings> dccplusplus;
|
||||
ObjectProperty<DecoderList> decoders;
|
||||
ObjectProperty<OutputList> outputs;
|
||||
|
||||
DCCPlusPlusInterface(const std::weak_ptr<World>& world, std::string_view _id);
|
||||
|
||||
@ -72,6 +76,12 @@ class DCCPlusPlusInterface final
|
||||
[[nodiscard]] bool addDecoder(Decoder& decoder) final;
|
||||
[[nodiscard]] bool removeDecoder(Decoder& decoder) final;
|
||||
void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber) final;
|
||||
|
||||
// OutputController:
|
||||
std::pair<uint32_t, uint32_t> outputAddressMinMax() const final { return {DCCPlusPlus::Kernel::outputAddressMin, DCCPlusPlus::Kernel::outputAddressMax}; }
|
||||
[[nodiscard]] bool addOutput(Output& output) final;
|
||||
[[nodiscard]] bool removeOutput(Output& output) final;
|
||||
[[nodiscard]] bool setOutputValue(uint32_t address, bool value) final;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2021 Reinder Feenstra
|
||||
* Copyright (C) 2021-2022 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -62,6 +62,7 @@ void Kernel::start()
|
||||
// reset all state values
|
||||
m_powerOn = TriState::Undefined;
|
||||
m_emergencyStop = TriState::Undefined;
|
||||
m_outputValues.fill(TriState::Undefined);
|
||||
|
||||
m_thread = std::thread(
|
||||
[this]()
|
||||
@ -214,6 +215,24 @@ void Kernel::decoderChanged(const Decoder& decoder, DecoderChangeFlags changes,
|
||||
}
|
||||
}
|
||||
|
||||
bool Kernel::setOutput(uint16_t address, bool value)
|
||||
{
|
||||
assert(inRange(address, outputAddressMin, outputAddressMax));
|
||||
|
||||
m_ioContext.post(
|
||||
[this, address, value]()
|
||||
{
|
||||
const auto index = address - outputAddressMin;
|
||||
if(m_outputValues[index] != toTriState(value))
|
||||
{
|
||||
m_outputValues[index] = toTriState(value);
|
||||
send(Ex::setAccessory(address - outputAddressMin, value));
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Kernel::setIOHandler(std::unique_ptr<IOHandler> handler)
|
||||
{
|
||||
assert(handler);
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2021 Reinder Feenstra
|
||||
* Copyright (C) 2021-2022 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -34,6 +34,7 @@
|
||||
class Decoder;
|
||||
enum class DecoderChangeFlags;
|
||||
class DecoderController;
|
||||
class OutputController;
|
||||
|
||||
namespace DCCPlusPlus {
|
||||
|
||||
@ -41,6 +42,10 @@ struct Message;
|
||||
|
||||
class Kernel
|
||||
{
|
||||
public:
|
||||
static constexpr uint16_t outputAddressMin = 1;
|
||||
static constexpr uint16_t outputAddressMax = 2044;
|
||||
|
||||
private:
|
||||
boost::asio::io_context m_ioContext;
|
||||
std::unique_ptr<IOHandler> m_ioHandler;
|
||||
@ -55,6 +60,9 @@ class Kernel
|
||||
|
||||
DecoderController* m_decoderController;
|
||||
|
||||
OutputController* m_outputController;
|
||||
std::array<TriState, outputAddressMax - outputAddressMin + 1> m_outputValues;
|
||||
|
||||
Config m_config;
|
||||
#ifndef NDEBUG
|
||||
bool m_started;
|
||||
@ -176,6 +184,18 @@ class Kernel
|
||||
m_decoderController = decoderController;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the output controller
|
||||
*
|
||||
* @param[in] outputController The output controller
|
||||
* @note This function may not be called when the kernel is running.
|
||||
*/
|
||||
inline void setOutputController(OutputController* outputController)
|
||||
{
|
||||
assert(!m_started);
|
||||
m_outputController = outputController;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start the kernel and IO handler
|
||||
*/
|
||||
@ -225,6 +245,14 @@ class Kernel
|
||||
*
|
||||
*/
|
||||
void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param[in] address Output address, #outputAddressMin..#outputAddressMax
|
||||
* @param[in] value Output value: \c true is on, \c false is off.
|
||||
* @return \c true if send successful, \c false otherwise.
|
||||
*/
|
||||
bool setOutput(uint16_t address, bool value);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2021 Reinder Feenstra
|
||||
* Copyright (C) 2021-2022 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -181,7 +181,7 @@ namespace Ex {
|
||||
|
||||
inline std::string setAccessory(uint16_t linearAddress, bool activate)
|
||||
{
|
||||
assert(linearAddress <= 2047);
|
||||
assert(linearAddress >= 1 && linearAddress <= 2044);
|
||||
|
||||
return std::string("<a ")
|
||||
.append(std::to_string(linearAddress))
|
||||
|
||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren