Files
MuditaOS/module-sys/Service/Timer.cpp
Przemyslaw Brudny 50d0cf0be9 [EGD-5598] GuiTimer refresh window on count
Added Gui timer auto refresh window on count and additional
name based API to detach timer from window. Added
TimerIDGenerator and exception throw on creating user timer
with same name.
2021-02-17 17:33:32 +01:00

114 lines
3.3 KiB
C++

// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "GuiTimer.hpp"
#include "Timer.hpp"
#include "Service.hpp"
#include "TimerMessage.hpp"
#include <log/log.hpp>
#include <projdefs.h>
#include <limits>
#include <memory>
#include <cstdint>
#if DEBUG_TIMER == 1
#define log(...) LOG_DEBUG(__VA_ARGS__)
#else
#define log_debug(...)
#endif
#define log_error(...) LOG_ERROR(__VA_ARGS__)
#define log_warn(...) LOG_WARN(__VA_ARGS__)
namespace sys
{
const ms Timer::timeout_infinite = std::numeric_limits<ms>().max();
Timer::Timer(const std::string &name, Service *service, ms interval, Type type, const TimerIDGenerator &generator)
: cpp_freertos::Timer(generator.generateID(name).c_str(), pdMS_TO_TICKS(interval), type == Type::Periodic),
parent(service), type(type), interval(interval), name(generator.generateID(name).c_str())
{
if (service != nullptr) {
if (service->timerExists(name)) {
throw std::runtime_error("Timer: " + name + " exits in service: " + service->GetName());
}
service->getTimers().attach(this);
generator.incrementID();
}
else {
log_error("Bad timer creation!");
}
log_debug("Timer %s created %s", name.c_str(), type == Type::Periodic ? "periodic" : "singleshot");
}
Timer::Timer(Service *parent, ms interval, Type type) : Timer("Timer", parent, interval, type)
{}
Timer::~Timer()
{
parent->getTimers().detach(this);
stop();
}
void Timer::Run()
{
auto msg = std::make_shared<TimerMessage>(this);
if (parent == nullptr) {
log_error("Timer %s error: no parent service", name.c_str());
return;
}
if (!parent->bus.sendUnicast(msg, parent->GetName())) {
LOG_ERROR("Timer %s error: bus error", name.c_str());
return;
}
}
void Timer::start()
{
log_debug("Timer %s start!", name.c_str());
isActive = true;
Start(0);
}
void Timer::reload(ms from_time)
{
Stop(0); // to avoid retriggering timer
if (from_time != 0) {
interval = from_time;
SetPeriod(pdMS_TO_TICKS(interval));
}
log_debug("Timer %s reload!", name.c_str());
isActive = true;
Start(0); // start with no waittime
}
void Timer::stop()
{
log_debug("Timer %s stop!", name.c_str());
// make sure callback is not called even if it is already in the queue
isActive = false;
Stop(0);
}
void Timer::setInterval(ms new_interval)
{
log_debug("Timer %s set interval to: %d ms!", name.c_str(), static_cast<unsigned int>(interval));
interval = new_interval;
SetPeriod(pdMS_TO_TICKS(new_interval), 0);
}
void Timer::onTimeout()
{
log_debug("Timer %s tick", name.c_str());
if (callback != nullptr && isActive) {
log_debug("Timer %s callback run!", name.c_str());
callback(*this);
return;
}
log_warn(
"callback from %s non valid - %d, or not active - %d", name.c_str(), callback == nullptr, isActive != true);
}
} // namespace sys