#72 Decoder.protocol is now limited by DecoderController
Dieser Commit ist enthalten in:
Ursprung
5d01de9b32
Commit
ab81ad73b3
@ -70,6 +70,11 @@ class SpanAttribute : public AbstractValuesAttribute
|
||||
return to<std::string>(m_values[index]);
|
||||
}
|
||||
|
||||
tcb::span<const T> values() const
|
||||
{
|
||||
return m_values;
|
||||
}
|
||||
|
||||
void setValues(tcb::span<const T> values)
|
||||
{
|
||||
if(m_values.size() != values.size() || std::memcmp(m_values.data(), values.data(), m_values.size()) != 0)
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2022 Reinder Feenstra
|
||||
* Copyright (C) 2019-2023 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -43,7 +43,20 @@ const std::shared_ptr<Decoder> Decoder::null;
|
||||
Decoder::Decoder(World& world, std::string_view _id) :
|
||||
IdObject(world, _id),
|
||||
name{this, "name", "", PropertyFlags::ReadWrite | PropertyFlags::Store},
|
||||
interface{this, "interface", nullptr, PropertyFlags::ReadWrite | PropertyFlags::Store, nullptr,
|
||||
interface{this, "interface", nullptr, PropertyFlags::ReadWrite | PropertyFlags::Store,
|
||||
[this](const std::shared_ptr<DecoderController>& value)
|
||||
{
|
||||
if(value)
|
||||
{
|
||||
assert(!value->decoderProtocols().empty());
|
||||
Attributes::setValues(protocol, value->decoderProtocols());
|
||||
checkProtocol();
|
||||
Attributes::setVisible(protocol, true);
|
||||
}
|
||||
else
|
||||
Attributes::setVisible(protocol, false);
|
||||
updateEditable();
|
||||
},
|
||||
[this](const std::shared_ptr<DecoderController>& newValue)
|
||||
{
|
||||
if(!newValue || newValue->addDecoder(*this))
|
||||
@ -60,6 +73,15 @@ Decoder::Decoder(World& world, std::string_view _id) :
|
||||
if(value == DecoderProtocol::DCC && DCC::isLongAddress(address))
|
||||
longAddress = true;
|
||||
updateEditable();
|
||||
},
|
||||
[this](DecoderProtocol& value)
|
||||
{
|
||||
if(interface)
|
||||
{
|
||||
const auto protocols = interface->decoderProtocols();
|
||||
return std::find(protocols.begin(), protocols.end(), value) != protocols.end();
|
||||
}
|
||||
return false;
|
||||
}},
|
||||
address{this, "address", 0, PropertyFlags::ReadWrite | PropertyFlags::Store,
|
||||
[this](const uint16_t& value)
|
||||
@ -121,7 +143,8 @@ Decoder::Decoder(World& world, std::string_view _id) :
|
||||
m_interfaceItems.add(interface);
|
||||
|
||||
Attributes::addEnabled(protocol, false);
|
||||
Attributes::addValues(protocol, decoderProtocolValues);
|
||||
Attributes::addValues(protocol, tcb::span<const DecoderProtocol>{});
|
||||
Attributes::addVisible(protocol, false);
|
||||
m_interfaceItems.add(protocol);
|
||||
|
||||
Attributes::addDisplayName(address, DisplayName::Hardware::address);
|
||||
@ -166,6 +189,10 @@ void Decoder::loaded()
|
||||
IdObject::loaded();
|
||||
if(interface)
|
||||
{
|
||||
Attributes::setValues(protocol, interface->decoderProtocols());
|
||||
Attributes::setVisible(protocol, true);
|
||||
checkProtocol(); //! \todo log something if protocol is changed??
|
||||
|
||||
if(!interface->addDecoder(*this))
|
||||
{
|
||||
if(auto object = std::dynamic_pointer_cast<Object>(interface.value()))
|
||||
@ -329,6 +356,18 @@ void Decoder::worldEvent(WorldState state, WorldEvent event)
|
||||
}
|
||||
}
|
||||
|
||||
bool Decoder::checkProtocol()
|
||||
{
|
||||
const auto protocols = protocol.getSpanAttribute<DecoderProtocol>(AttributeName::Values).values();
|
||||
assert(!protocols.empty());
|
||||
if(auto it = std::find(protocols.begin(), protocols.end(), protocol); it == protocols.end())
|
||||
{
|
||||
protocol = protocols.front();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Decoder::updateEditable()
|
||||
{
|
||||
updateEditable(contains(m_world.state.value(), WorldState::Edit));
|
||||
@ -339,7 +378,7 @@ void Decoder::updateEditable(bool editable)
|
||||
const bool stopped = editable && almostZero(throttle.value());
|
||||
Attributes::setEnabled(name, editable);
|
||||
Attributes::setEnabled(interface, stopped);
|
||||
Attributes::setEnabled(protocol, stopped);
|
||||
Attributes::setEnabled(protocol, stopped && protocol.getSpanAttribute<DecoderProtocol>(AttributeName::Values).length() > 1);
|
||||
Attributes::setEnabled(address, stopped);
|
||||
Attributes::setEnabled(longAddress, stopped && protocol == DecoderProtocol::DCC && !DCC::isLongAddress(address));
|
||||
Attributes::setEnabled(speedSteps, stopped);
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2022 Reinder Feenstra
|
||||
* Copyright (C) 2019-2023 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -52,6 +52,12 @@ class Decoder : public IdObject
|
||||
void loaded() final;
|
||||
void destroying() override;
|
||||
void worldEvent(WorldState state, WorldEvent event) final;
|
||||
|
||||
//! \brief Check and correct protocol
|
||||
//! If the current value isn't in the list of valid protocols the protocol is set the the first valid one.
|
||||
//! \return \c true if adjusted, \c false if unchanged
|
||||
bool checkProtocol();
|
||||
|
||||
void updateEditable();
|
||||
void updateEditable(bool editable);
|
||||
void changed(DecoderChangeFlags changes, uint32_t functionNumber = 0);
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2021-2022 Reinder Feenstra
|
||||
* Copyright (C) 2021-2023 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -26,6 +26,7 @@
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <tcb/span.hpp>
|
||||
#include "../../core/objectproperty.hpp"
|
||||
|
||||
#ifdef interface
|
||||
@ -64,6 +65,10 @@ class DecoderController
|
||||
public:
|
||||
ObjectProperty<DecoderList> decoders;
|
||||
|
||||
//! \brief Get supported protocols
|
||||
//! \return Supported protocols, may not be empty and must be constant for the instance!
|
||||
virtual tcb::span<const DecoderProtocol> decoderProtocols() const = 0;
|
||||
|
||||
[[nodiscard]] bool addDecoder(Decoder& decoder);
|
||||
[[nodiscard]] bool removeDecoder(Decoder& decoder);
|
||||
|
||||
|
||||
@ -77,6 +77,12 @@ DCCPlusPlusInterface::DCCPlusPlusInterface(World& world, std::string_view _id)
|
||||
m_interfaceItems.insertBefore(outputs, notes);
|
||||
}
|
||||
|
||||
tcb::span<const DecoderProtocol> DCCPlusPlusInterface::decoderProtocols() const
|
||||
{
|
||||
static constexpr std::array<DecoderProtocol, 1> protocols{DecoderProtocol::DCC};
|
||||
return tcb::span<const DecoderProtocol>{protocols.data(), protocols.size()};
|
||||
}
|
||||
|
||||
void DCCPlusPlusInterface::decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber)
|
||||
{
|
||||
if(m_kernel)
|
||||
|
||||
@ -74,6 +74,7 @@ class DCCPlusPlusInterface final
|
||||
DCCPlusPlusInterface(World& world, std::string_view _id);
|
||||
|
||||
// DecoderController:
|
||||
tcb::span<const DecoderProtocol> decoderProtocols() const final;
|
||||
void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber) final;
|
||||
|
||||
// InputController:
|
||||
|
||||
@ -69,6 +69,12 @@ ECoSInterface::ECoSInterface(World& world, std::string_view _id)
|
||||
m_interfaceItems.insertBefore(outputs, notes);
|
||||
}
|
||||
|
||||
tcb::span<const DecoderProtocol> ECoSInterface::decoderProtocols() const
|
||||
{
|
||||
static constexpr std::array<DecoderProtocol, 3> protocols{DecoderProtocol::DCC, DecoderProtocol::Motorola, DecoderProtocol::Selectrix};
|
||||
return tcb::span<const DecoderProtocol>{protocols.data(), protocols.size()};
|
||||
}
|
||||
|
||||
void ECoSInterface::decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber)
|
||||
{
|
||||
if(m_kernel)
|
||||
|
||||
@ -73,6 +73,7 @@ class ECoSInterface final
|
||||
ECoSInterface(World& world, std::string_view _id);
|
||||
|
||||
// DecoderController:
|
||||
tcb::span<const DecoderProtocol> decoderProtocols() const final;
|
||||
void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber) final;
|
||||
|
||||
// InputController:
|
||||
|
||||
@ -131,6 +131,12 @@ bool LocoNetInterface::immPacket(tcb::span<uint8_t> dccPacket, uint8_t repeat)
|
||||
return false;
|
||||
}
|
||||
|
||||
tcb::span<const DecoderProtocol> LocoNetInterface::decoderProtocols() const
|
||||
{
|
||||
static constexpr std::array<DecoderProtocol, 1> protocols{DecoderProtocol::DCC};
|
||||
return tcb::span<const DecoderProtocol>{protocols.data(), protocols.size()};
|
||||
}
|
||||
|
||||
void LocoNetInterface::decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber)
|
||||
{
|
||||
if(m_kernel)
|
||||
|
||||
@ -94,6 +94,7 @@ class LocoNetInterface final
|
||||
bool immPacket(tcb::span<uint8_t> dccPacket, uint8_t repeat);
|
||||
|
||||
// DecoderController:
|
||||
tcb::span<const DecoderProtocol> decoderProtocols() const final;
|
||||
void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber) final;
|
||||
|
||||
// InputController:
|
||||
|
||||
@ -156,6 +156,12 @@ XpressNetInterface::XpressNetInterface(World& world, std::string_view _id)
|
||||
updateVisible();
|
||||
}
|
||||
|
||||
tcb::span<const DecoderProtocol> XpressNetInterface::decoderProtocols() const
|
||||
{
|
||||
static constexpr std::array<DecoderProtocol, 1> protocols{DecoderProtocol::DCC};
|
||||
return tcb::span<const DecoderProtocol>{protocols.data(), protocols.size()};
|
||||
}
|
||||
|
||||
void XpressNetInterface::decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber)
|
||||
{
|
||||
if(m_kernel)
|
||||
|
||||
@ -82,6 +82,7 @@ class XpressNetInterface final
|
||||
XpressNetInterface(World& world, std::string_view _id);
|
||||
|
||||
// DecoderController:
|
||||
tcb::span<const DecoderProtocol> decoderProtocols() const final;
|
||||
void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber) final;
|
||||
|
||||
// InputController:
|
||||
|
||||
@ -87,6 +87,12 @@ Z21Interface::Z21Interface(World& world, std::string_view _id)
|
||||
m_interfaceItems.insertBefore(firmwareVersion, notes);
|
||||
}
|
||||
|
||||
tcb::span<const DecoderProtocol> Z21Interface::decoderProtocols() const
|
||||
{
|
||||
static constexpr std::array<DecoderProtocol, 2> protocols{DecoderProtocol::DCC, DecoderProtocol::Motorola};
|
||||
return tcb::span<const DecoderProtocol>{protocols.data(), protocols.size()};
|
||||
}
|
||||
|
||||
void Z21Interface::decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber)
|
||||
{
|
||||
if(m_kernel)
|
||||
|
||||
@ -73,6 +73,7 @@ class Z21Interface final
|
||||
Z21Interface(World& world, std::string_view _id);
|
||||
|
||||
// DecoderController:
|
||||
tcb::span<const DecoderProtocol> decoderProtocols() const final;
|
||||
void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber) final;
|
||||
|
||||
// InputController:
|
||||
|
||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren