sTodo-m5paper-client/libraries/M5UnitUnified/src/M5UnitUnified.cpp
2025-06-30 20:47:33 +02:00

150 lines
3.8 KiB
C++

/*
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
/*!
@file M5UnitUnified.cpp
@brief class UnitUnified
*/
#include "M5UnitUnified.hpp"
#include <M5Utility.hpp>
namespace m5 {
namespace unit {
uint32_t UnitUnified::_registerCount{0};
bool UnitUnified::add(Component& u, m5::hal::bus::Bus* bus)
{
if (u.isRegistered()) {
M5_LIB_LOGW("Already added");
return false;
}
if (!bus) {
M5_LIB_LOGE("Bus null");
return false;
}
M5_LIB_LOGD("Add [%s]:0x%02x", u.deviceName(), u.address());
u._manager = this;
if (u.assign(bus)) {
u._order = ++_registerCount;
_units.emplace_back(&u);
return add_children(u);
}
M5_LIB_LOGE("Failed to assign %s:%u", u.deviceName(), u.canAccessI2C());
return false;
}
bool UnitUnified::add(Component& u, TwoWire& wire)
{
if (u.isRegistered()) {
M5_LIB_LOGW("Already added");
return false;
}
M5_LIB_LOGD("Add [%s] addr:%02x children:%zu", u.deviceName(), u.address(), u.childrenSize());
u._manager = this;
if (u.assign(wire)) {
u._order = ++_registerCount;
_units.emplace_back(&u);
return add_children(u);
}
M5_LIB_LOGE("Failed to assign %s:%u", u.deviceName(), u.canAccessI2C());
return false;
}
bool UnitUnified::add(Component& u, const int8_t rx_pin, const int8_t tx_pin)
{
if (u.isRegistered()) {
M5_LIB_LOGW("Already added");
return false;
}
M5_LIB_LOGD("Add [%s] rx:%d tx:%d %zu", u.deviceName(), rx_pin, tx_pin, u.childrenSize());
u._manager = this;
if (u.assign(rx_pin, tx_pin)) {
u._order = ++_registerCount;
_units.emplace_back(&u);
return add_children(u);
}
M5_LIB_LOGE("Failed to assign %s:%u", u.deviceName(), u.canAccessGPIO());
return false;
}
// Add children if exists
bool UnitUnified::add_children(Component& u)
{
auto it = u.childBegin();
while (it != u.childEnd()) {
auto ch = it->channel();
M5_LIB_LOGV("%s child:%s channel:%u", u.deviceName(), it->deviceName(), ch);
if (it->isRegistered()) {
M5_LIB_LOGE("Already registered %s", it->deviceName());
return false;
}
it->_manager = this;
it->_adapter = u.ensure_adapter(ch);
M5_LIB_LOGD(" Shared:%u %u", u._adapter.use_count(), it->_adapter.use_count());
it->_order = ++_registerCount;
_units.emplace_back(&*it);
if (!add_children(*it)) {
return false;
}
++it;
}
return true;
}
bool UnitUnified::begin()
{
return !std::any_of(_units.begin(), _units.end(), [](Component* c) {
M5_LIB_LOGV("Try begin:%s", c->deviceName());
bool ret = c->_begun = c->begin();
if (!ret) {
M5_LIB_LOGE("Failed to begin: %s", c->debugInfo().c_str());
}
return !ret;
});
}
void UnitUnified::update(const bool force)
{
// Order of registration
for (auto&& u : _units) {
if (!u->_component_cfg.self_update && u->_begun) {
u->update(force);
}
}
}
std::string UnitUnified::debugInfo() const
{
std::string s = m5::utility::formatString("\nM5UnitUnified: %zu units\n", _units.size());
for (auto&& u : _units) {
if (!u->hasParent()) {
s += make_unit_info(u, 0);
}
}
return m5::utility::trim(s);
}
std::string UnitUnified::make_unit_info(const Component* u, const uint8_t indent) const
{
std::string s = m5::utility::formatString("%*c%s\n", indent * 4, ' ', u->debugInfo().c_str());
if (u->hasChildren()) {
s += make_unit_info(u->_child, indent + 1);
}
u = u->_next;
return u ? s += make_unit_info(u, indent) : s;
}
} // namespace unit
} // namespace m5